Atomic** 类
采用的是CAS方式
LongAdder类
采用的是分段锁
package juc.lock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
public class AtomicVSSynchronized {
static long count1 = 0;
static AtomicInteger count2 = new AtomicInteger(0);
static LongAdder count3 =new LongAdder();
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[1000];
for(int i = 0; i< threads.length; i++)
threads[i] = new Thread(()-> {
for(int j = 0; j < 1000; j++)
count2.incrementAndGet();
});
long start = System.currentTimeMillis();
for(Thread thread:threads) thread.start();
for(Thread thread:threads) thread.join();
long end = System.currentTimeMillis();
System.out.println("Atmic**:"+ (end - start));
/
Object lock = new Object();
for(int i =0; i< threads.length; i++)
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0 ; i< 1000; i++)
synchronized(lock) {
count1++;
};
}
});
start = System.currentTimeMillis();
for(Thread thread:threads) thread.start();
for(Thread thread:threads) thread.join();
end = System.currentTimeMillis();
System.out.println("Synchronized**:"+ (end - start));
/
for(int i = 0; i< threads.length; i++)
threads[i] = new Thread(()-> {
for(int j = 0; j < 1000; j++)
count3.increment();
});
start = System.currentTimeMillis();
for(Thread thread:threads) thread.start();
for(Thread thread:threads) thread.join();
end = System.currentTimeMillis();
System.out.println("Atmic**:"+ (end - start));
}
}
如果线程数多的情况下,可能LongAdder的速度会快些. LongAdder采用的是把不同的线程进行分组,最后再进行统计加和,当然每个线程采用的还是CAS的方式。
ReentrantLock
有以下的特性
- 公平与不公平锁, 可以规定是fair还是不fair。公平锁的话,每个线程都拿到这个锁的概率都是公平的,进入同一段代码的概率都是一致的。默认是非公平锁。
-
package juc.lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLOCK_FAIR implements Runnable { static ReentrantLock lock = new ReentrantLock(true); public void run() { for(int i = 0;i < 100;i++) { lock.lock(); try { System.out.println(Thread.currentThread().getName()); }finally { lock.unlock(); } } } public static void main(String[] args) { ReentrantLOCK_FAIR r1 = new ReentrantLOCK_FAIR(); Thread t1 =new Thread(r1); Thread t2 =new Thread(r1); t1.start(); t2.start(); } }
- trylock
- lockInterruptibly
reentrantLock 和synchronized的不同
1. 底层实现,reentrantLock是使用CAS, synchronized是使用系统锁
2. synchronized不需要手动锁和解锁,reentrantLock需要手动调用锁和解锁
3. reentrantLock有一些特殊的接口,synchronized没有
CountDownLatch
- 和join很像。每个线程执行一次,对latch减一,当为零的时候,latch就打开了。
-
package juc.lock; import java.util.concurrent.CountDownLatch; public class UsingCountDown { public void usingCountDown() { Thread[] threads = new Thread[100]; CountDownLatch latch = new CountDownLatch(threads.length); for(int i = 0 ; i < threads.length; i++) { threads[i] = new Thread(()->{ int result = 0; for(int j = 0 ; j < 10000; j++ ) result+=1; latch.countDown(); }); } try { latch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for(int i = 0 ; i< threads.length;i++) threads[i].start(); System.out.println("end latch"); } }
- CyclicBarrier
比如有一个任务要等待好几个任务都结束才能跑,就可以用这个接口。
-
package juc.lock; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class TestCyclicBarrier { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() { public void run() { System.out.println("满人,发车"); } }); for(int i = 0 ; i< 100;i++) { new Thread(()->{ try { barrier.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } }).start(); } } }
ReentrantReadWriteLock
- ReadLock 允许读的线程进来,但是不允许写的线程进来。同样,WriteLock不允许任何别的线程进来
-
package juc.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class TestReadWriteLock { static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); static int value = 0; static Lock readl = readWriteLock.readLock(); static Lock writel = readWriteLock.writeLock(); public static void read(Lock lock) { try { lock.lock(); Thread.sleep(1000); System.out.println("read over"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } public static void write(Lock lock,int v) { try { lock.lock(); value =v; Thread.sleep(1); System.out.println("write over"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) { Runnable readR = ()-> read(readl); Runnable writeR = ()-> write(writel,2); for(int i =0 ; i < 12; i++) { new Thread(readR).start() ; } for(int i =0 ; i < 2; i++) { new Thread(writeR).start() ; } } }