码迷,mamicode.com
首页 > 其他好文 > 详细

锁相关

时间:2021-06-02 12:49:40      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:vol   内存   fifo   接下来   vat   writer   共享锁   相等   await   

1、CAS

 多个线程同CAS更新同一个变量,只有一个线程能成功,其他的都失败,但不会挂起,只是通知其他线程再次尝试。

包含三个值:内存值V,进行比较的预期原值A、准备写入的新值B。如果V和A相等,则将V更新为B。

2、AQS(AbstractQueuedSynchronizer)

内部通过Node构成同步队列来完成线程获取锁的排队工作,通过另一个内部类ConditionObject完成等待队列,调用await()后,线程加入等待队列,调用signal()方法后,线程移入同步队列进行锁竞争。

 

 

内部通过一个被volatile修饰的变量state来控制同步状态。0-锁未占用 1-锁占用  通过CAS操作来对变量state的改变保证一致性。

通过内部类Node构成FIFO队列来完成线程获取锁的排队工作。

node.prev = pred = pred.prev;
pred.prev:新增的节点之前的节点B的之前的节点A
pred = pred.prev:把A赋值B,原先的pred的pred.prev就变了。
node.prev = pred :让新增的节点中pre的属性指向
整个表达式相当于node的pred指向都跳过前一个的node。

             -------<--------
A          |       B          | NODE
------     |     ------       |  ------
|prev|<-|    |prev|      |--|prev|
|next|         |next|         |next|
------           ------         ------

 

park() 阻塞线程 unpark() 唤醒线程

 

ReentrantLock:(是个可重入锁)
  Sync extends AbstractQueuedSynchronizer
       非公平锁(默认):NonfairSync endtends Sync  通过一个CAS操作判断是否可以将当前线程设置为拥有锁,不可以则和公平锁一样,排队。
       公平锁                  : FairSync entends Sync

        可以通过重写了AQS的tryAquire和tryRelease方法自定义了获取锁和释放锁的逻辑。

加锁过程:

         tf:第一个线程  t2:其他线程

如果是tf,则线程直接持有锁,和AQS队列无关。

如果有其他线程竞争,则会初始化AQS(对内部类Node中的属性初始化:head = node;node.thread = null;node.prev = null;)会在头部虚拟一个Thread=null的Node,t2会自己封装一个Thread!=null的Node,此时队列中除了head以外的Node都在park(阻塞),当tf释放之后unpark(唤醒)某个Node,node被唤醒,如果node是由t2封装的,则首先会把t2的Node设置为head,并通过setThread方法把Thread==null。(t2已经获取到锁了,node就不需要排队了,node中对Thread的引用没有意义了)

 

ReentrantReadWriteLock :

  ReadLock:共享锁模式

  WriteLock:独占锁模式

 1 public class ReadWriteRockDemo1 {
 2     private final static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 3     private final static ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
 4     private final static ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
 5     private static int count = 1000;
 6     private final static ReentrantLock lock =new ReentrantLock();
 7 
 8     //这样不行,仍然会有负数打印出来
 9     public static void main(String[] args) {
10         lock.lock();
11         while (true) {
12             new Thread(() -> {
13                 while (count > 0) {
14                     readLock.lock();
15                     System.out.println("####################");
16                     if (count <= 0) {
17                         System.out.println("@@@@@@@@@@@@@@@@@@@@" + count);
18                         break;
19                     }
20                     readLock.unlock();
21 
22                     writeLock.lock();//此时readLock.lock()会被阻塞,因为writeLock是独占锁,此时可能会有多个readLock被阻塞着
23                     //当writeLock锁释放完后,readLock阻塞的多个线程会同时获取锁,同时运行接下来的代码,导致count<0判断失效
24                     --count;
25                     System.out.println("************" + count);
26                     writeLock.unlock();
27                 }
28             }).start();
29         }
30 
31 
32     }
33 }

 




锁相关

标签:vol   内存   fifo   接下来   vat   writer   共享锁   相等   await   

原文地址:https://www.cnblogs.com/zt1991jskj/p/13087134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!