当前位置 : 主页 > 网络编程 > 其它编程 >

synchronized和Lock区别转载

来源:互联网 收集:自由互联 发布时间:2023-07-02
synchronized和Lock区别原始构成使用方法等待是否可中断加锁是否公平锁绑定多个条件Condition原始构成sychronized是关键字属于JVM层面的 monitorenter、monitorexit底层是通过monitor对象来完成的其实
synchronized和Lock区别原始构成使用方法等待是否可中断加锁是否公平锁绑定多个条件Condition原始构成sychronized是关键字属于JVM层面的 monitorenter、monitorexit底层是通过monitor对象来完成的其实wait/notify方法也依赖于monitor对象只有在同步块或者同步方法中才能调用wait/notify等方法 Lock属于具体类java.util.concurrent.locks.lock是api层面的锁。

使用方法

synchronized不需要用户手动去释放锁当synchronized代码执行完成后系统会自动让线程释放对锁的占用 ReentrantLock则需要用户手动去释放锁若没有主动释放锁就有可能导致出现死锁现象。需要lock()、unlock()方法配合try/finally语句块来完成。

等待是否可中断

synchronized不可中断除非抛出异常或者正常运行完成 ReentrantLock可中断: 设置超时方法tryLock(long timeout, TimeUnit unit)lockInterruptibly()放代码块中调用interrupt()方法可中断

补充synchronized重入后抛出异常锁释放了

synchronized用于同步方法或者代码块使得多个线程在试图并发执行同一个代码块的时候串行地执行。以达到线程安全的目的。

在多线程的时候是这样的但是对于单线程是允许重入的每重入一次计数器加1当退出代码块时计数器减1。

那正常退出时计数器减1抛异常时计数器也是减1。那如果两次重入在内层抛出异常会释放锁吗还是只会计数器减1锁并不会释放

直接上代码

public class SynchronizedTest1 {public static void main(String[] args){Test test1 new Test();Thread thread1 new Thread(test1);Thread thread2 new Thread(test1);thread1.start();thread2.start();}}class Test implements Runnable{public synchronized void hello() throws Exception{System.out.println(Thread.currentThread().getName() " say hello!!");sorry();System.out.println(Thread.currentThread().getName() " helloed");}public synchronized void sorry() throws Exception{System.out.println(Thread.currentThread().getName() " say sorry!!");throw new Exception(Thread.currentThread().getName() " this is a test!");}public void run() {try {hello();}catch (Exception e){System.out.println(Thread.currentThread().getName() " exception once");}try {Thread.sleep(10000L);System.out.println(Thread.currentThread().getName() " exit");}catch (Exception e){System.out.println(Thread.currentThread().getName() " some exception");}}}

Thread-0 say hello!!Thread-0 say sorry!!Thread-0 exception onceThread-1 say hello!!Thread-1 say sorry!!Thread-1 exception onceThread-1 exitThread-0 exitProcess finished with exit code 0

从以上运行结果得出以下结论synchronized重入之后抛出异常跳出synchronized代码块会释放锁。

原文https://www.cnblogs.com/catchmydream/p/10079643.html

加锁是否公平

synchronized非公平锁 ReentrantLock两者都可以默认是非公平锁构造方法可以传入boolean值传入的值为true表示公平锁传入的值为false表示非公平锁。

补充公平锁和非公平锁的理解

公平锁多个线程按照申请锁的顺序去获得锁线程会直接进入队列去排队永远都是队列的第一位才能得到锁。

优点所有的线程都能得到资源不会饿死在队列中。缺点吞吐量会下降很多队列里面除了第一个线程其他的线程都会阻塞cpu唤醒阻塞线程的开销会很大。

非公平锁多个线程去获取锁的时候会直接去尝试获取获取不到再去进入等待队列如果能获取到就直接获取到锁。

优点可以减少CPU唤醒线程的开销整体的吞吐效率会高点CPU也不必取唤醒所有线程会减少唤起线程的数量。缺点你们可能也发现了这样可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁导致饿死。

转载链接 https://www.imooc.com/article/302143

锁绑定多个条件Condition

synchronized不能绑定多个条件 ReentrantLock用来实现分组需要唤醒的线程们可以精确唤醒而不像synchronized那样随便唤醒一个线程或者全部线程。

补充锁绑定多个条件Condition的理解

锁绑定多个条件Condition代码conditionA.await()阻塞conditionA.signal()唤醒

package com.lxk.lock;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/*** 锁绑定多个条件Condition * 题目多线程之间按顺序执行实现A->B->C三个线程启动要求如下 A打印5次B打印10次C打印15次* 紧接着 A打印5次B打印10次C打印15次 . . . 循环执行10轮*/public class LockConditionDemo {public static void main(String[] args) {ShareResource shareResource new ShareResource();new Thread(() -> {for (int i 0; i {for (int i 0; i {for (int i 0; i <10; i) {shareResource.print15();}} , "C").start();}}/*** 共享资源类*/class ShareResource {// A:1 B:2 C:30private int num 1;private Lock lock new ReentrantLock();private Condition conditionA lock.newCondition();private Condition conditionB lock.newCondition();private Condition conditionC lock.newCondition();// 循环打印5次public void print5() {// 1、获取锁资源lock.lock();try {// 2、判断是否可以执行业务while (num ! 1) {// 阻塞等待conditionA.await();}// 模拟业务执行for (int i 0; i <5; i) {System.out.println(Thread.currentThread().getName() "\t" (i 1));}// 3、通知其他线程通过signal()方法唤醒线程num 2;conditionB.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}// 循环打印10次public void print10() {// 1、获取锁资源lock.lock();try {// 2、判断是否可以执行业务while (num ! 2) {conditionB.await();}// 模拟业务执行for (int i 0; i <10; i) {System.out.println(Thread.currentThread().getName() "\t" (i 1));}// 3、通知其他线程num 3;conditionC.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}// 循环打印15次public void print15() {// 1、获取锁资源lock.lock();try {// 2、判断是否可以执行业务while (num ! 3) {conditionC.await();}// 模拟业务执行for (int i 0; i <15; i) {System.out.println(Thread.currentThread().getName() "\t" (i 1));}// 3、通知其他线程num 1;conditionA.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}

结果分析符合预期 在这里插入图片描述

转载链接 https://blog.csdn.net/lixinkuan328/article/details/94426872

上一篇:vector容器怎么初始化
下一篇:没有了
网友评论