1.CountDownLatch的作用?
信号量jdk1.5之后出现的,CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。2.CyclicBarrier
CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。
当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
以上这两个可以当做计数器来使用,只不过countDownLatch规定数目之后每次减一,到0的时候唤醒继续执行,
而CyclicBarrier是规定一个数目之后,每次加一,当加到规定数目之后,唤醒继续执行。
3.Semaphore 信号量
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。
举一个例子,比如ABCDE5个人,阈值为2,每次抢到的资源的只有两个,假如首先抢到的是AC两人,剩下的3个人进行等待,AC他们执行完,会放回阈值,剩下的三个人会去抢资源,也只能有两个人抢到,执行完毕之后放过阈值,最后一个人拿到之后再执行。
4.并发队列 ConcurrentLinkedQueue和BlockingQueue
一个是以ConcurrentLinkedQueue为代表的高性能队列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪种都继承自Queue。ConcurrentLinkedDeque : 通过无锁的方式,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许null元素。
BlockingQueue:阻塞队列,阻塞有界(就是数量有限制)。典型就是ArrayBlockingQueue 和 LinkedBlockingQueue
这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
5.悲观锁和乐观锁
悲观锁:悲观锁悲观的认为每一次操作都会造成更新丢失问题,在每次查询时加上排他锁。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。乐观锁:乐观锁会乐观的认为每次查询都不会造成更新丢失,利用版本字段控制
6.重入锁
重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁
7.读写锁(互斥锁)
在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。
8.CAS无锁机制
CAS算法的过程是这样:它包含三个参数CAS(V,E,N): V内存地址,E期望值,N新值。如果内存地址的值==期望值,表示该值未修改,此时可以修改成新值。否则表示修改失败,CAS返回当前V的真实值,由用户决定后续操作。
可以这么理解其实有一个变量int a =6 ,v=6,E=6,n=8(我要修改的变量是a=6,我期望它现在是6,因为这样我可以把它变成8,)如果期望值6如果和当前的变量a的值不同,那就说明已经被人修改过了,我是不能做操作的。
当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程不会被挂起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。基于这样的原理,CAS操作即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。
9.自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。

本文介绍了多种并发控制机制,包括CountDownLatch、CyclicBarrier、Semaphore、并发队列等,并对比了它们的特点与应用场景。此外,还深入探讨了悲观锁、乐观锁、重入锁、读写锁、CAS算法、自旋锁的概念及工作原理。
171万+

被折叠的 条评论
为什么被折叠?



