信号量Semaphore,AtomicInteger
countDownlunch:多线程阻塞控制,线程池所有线程执行完后,主线程继续执行
信号量Semaphore:多线程可同时使用资源控制
java.util.concurrent.CountDownLatch
java.util.concurrent.Semaphore
java.util.concurrent.locks.ReentrantLock
java.util.concurrent.atomic.AtomicInteger
首先在java层面,reentrantlock以及其他同步工具类,比如ConcurrentHashMap,CountDownLatch,CyclicBarrier,以及信号量 semaphore,在底层都是通过实现抽象类AbstractQueuedSynchronizer(AQS)来实现各种锁功能,比如乐观锁,悲观锁,互斥锁,共享锁,读写锁等,在java层面通过继承AQS,然后配合unsafe提供的CAS操作以及链表这个数据结构,去实现乐观锁,互斥,共享,自旋等锁,当需要阻塞线程的时候,通过unsafe类调用操作系统的mutex互斥锁去实现阻塞。
ReentrantLock
lock方法实现 AbstractQueuedSynchronizer.compareAndSetState unsafe.compareAndSwapInt
Semaphore
semp.acquire()方法实现 AbstractQueuedSynchronizer.acquireSharedInterruptibly compareAndSetState
首先要说一下,AtomicInteger类compareAndSet通过原子操作实现了CAS操作,最底层基于汇编语言实现。
简单说一下原子操作的概念,“原子”代表最小的单位,所以原子操作可以看做最小的执行单位,该操作在执行完毕前不会被任何其他任务或事件打断。
CAS是Compare And Set的一个简称,如下理解:
1,已知当前内存里面的值current和预期要修改成的值new传入
2,内存中AtomicInteger对象地址对应的真实值(因为有可能别修改)real与current对比,
相等表示real未被修改过,是“安全”的,将new赋给real结束然后返回;不相等说明real已经被修改,结束并重新执行1直到修改成功
public int incrementAndGetModulo(AtomicInteger ai) {
for (;;) {
int current = ai.get();
System.out.println(Thread.currentThread().getName()+" currentBefore "+current);
int next =(current+1) ;
if (ai.compareAndSet(current, next)){
System.out.println(Thread.currentThread().getName()+"********current:"+current+"next"+next);//compareAndSet 保存next,如果在执行过程中其他线程改变了current,则本次保存不成功,继续循环取值
return (int)next;
}
}
}
AtomicIntegerTest ait = new AtomicIntegerTest();
AtomicInteger ai = new AtomicInteger();
Thread t1 = new Thread(){
public void run() {
System.out.println("t1 "+Thread.currentThread().getName());
int i = 0;
while (i++ < 10)
ait.incrementAndGetModulo(ai);
}
};
Thread t2 = new Thread(){
public void run() {
System.out.println("t2 "+Thread.currentThread().getName());
int i = 0;
while (i++ < 10)
ait.incrementAndGetModulo(ai);
}
};
快速实现 int re = ai.getAndIncrement();//返回旧值(即加1前的原始值) 返回旧值(即加1前的原始值)
public int getNum(AtomicInteger atomicInteger){
while (true){
int i = atomicInteger.get();
int m = i+1;
if(atomicInteger.compareAndSet(i,m)){
return m;
}
}
};
public static void main(String[] args) {
AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTest();
AtomicInteger atomicInteger = new AtomicInteger();
for(int i=0;i<100;i++){
System.out.println(atomicIntegerTest.getNum(atomicInteger));
}
}
信号量Semaphore(如果一段业务只允许一个线程执行就可以把信号量设为1,当再启动一个线程时去获取信号量,当上一个线程执行完后会释放信号量,此时第二个线程就可以获取信号量进而执行代码,两个线程需公用同一个Semaphore实体)
package cn.com.xmh.test;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class TestClass {
/**
* 1,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可
* 2,如果是线程实现类中,Semaphore必须是静态的,所有线程共享一个Semaphore
*/
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
//while(true){
String tname = Thread.currentThread().getName();
try {
// 获取许可
//System.out.println(tname+" --------acqueir before---------"+ semp.availablePermits());
semp.acquire();
Random random = new Random();
int i=random.nextInt(10);
System.out.println(tname+" Accessing: " + NO+" sleep:"+i+" -----占用----"+ semp.availablePermits());
Thread.sleep((long) (i * 1000));
// 访问完后,释放
semp.release();
System.out.println(tname+" -------release----------"+ semp.availablePermits());//有可能刚释放就被阻塞的线程获取到信号,这里可用信号就为0
} catch (InterruptedException e) {
e.printStackTrace();
}
//}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();//no new tasks will be accepted
}
}
多线程
public class ThreadFirst extends Thread{
private ThreadTest test;
public ThreadFirst(ThreadTest tt) {
this.test = tt;
}
public void run(){
//while(true){
test.test();
//}
}
}
public class ThreadSecond extends Thread{
private ThreadTest test;
public ThreadSecond(ThreadTest tt) {
this.test = tt;
}
public void run(){
//while(true){
test.test();
//}
}
}
public class ThreadTest {
public synchronized void test(){
for(int i = 0; i < 10; i++){
if(i == 5){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
this.notifyAll();
}
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}

浙公网安备 33010602011771号