CAS(无锁优化)
伪代码解释
cas(V,Expected,NewValue) {
if V==E
V == NewValue
otherwise try again or fail
}
V(当前值),Expected(期望值),NewValue(新值)
当v等于e时,将n赋予v,否则进行自旋操作
ABA问题
在进行cas时,有线程更改了v,之后又更改回来,让程序以为没发生改变
解决方案
设立版本号,在cas时加上版本号比较,atmic包中存在版本号的类
ReentrantLock
Lock lock = new ReentrantLock();
try {
lock.lock();
......
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
ReentrantLock需要手动解锁,synchronized自动解锁,两把锁都是可重入锁
ReentrantLock可以替代synchronized,ReentrantLock还拥有synchronized不存在的方法
tryLock()
tryLock()可以设置超时时间,当线程未在指定时间内获得锁便立刻返回false,反之返回true。
boolean locked = false;
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
System.out.println("m2 ..." + locked);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (locked) lock.unlock();
}
lockInterruptibly()
ReentrantLock.lockInterruptibly允许在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException。
ReentrantLock(true)
指定ReentrantLock为公平锁,即线程的执行是按照FIFO的顺序执行的(并不绝对)
CountDownLatch
通过计数控制锁的锁定和开启
CountDownLatch是原子类
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 += j;
latch.countDown();
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
CyclicBarrier
监听等待在CyclicBarrier上的线程数量,一旦达到指定的数量,就执行CyclicBarrier参数二上的线程,之后重新进行监听,循环往复。
CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
@Override
public void run() {
System.out.println("满人,发车");
}
for(int i=0; i<100; i++) {
new Thread(()->{
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
Phaser
分段执行各个线程(类似先异步后同步)
ReadWriteLock
共享锁/写锁 : readWriteLock.readLock()
排它锁/读锁/互斥锁/独占锁 : readWriteLock.writeLock()
static Lock lock = new ReentrantLock();
private static int value;
static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();
static Lock writeLock = readWriteLock.writeLock();
public static void read(Lock lock) {
try {
lock.lock();
Thread.sleep(1000);
System.out.println("read over!");
//模拟读取操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void write(Lock lock, int v) {
try {
lock.lock();
Thread.sleep(1000);
value = v;
System.out.println("write over!");
//模拟写操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
//Runnable readR = ()-> read(lock);
Runnable readR = ()-> read(readLock);
//Runnable writeR = ()->write(lock, new Random().nextInt());
Runnable writeR = ()->write(writeLock, new Random().nextInt());
for(int i=0; i<18; i++) new Thread(readR).start();
for(int i=0; i<2; i++) new Thread(writeR).start();
}
Semaphore
semaphore的作用是限流,可以指定同时运行线程的个数
Semaphore s = new Semaphore(1);
。。。
// acquire的作用是线程获取锁,只有获取到锁的线程才能继续执行
s.acquire();
。。。
Exchanger
用于交换两个线程的数据,需要同时调用exchanger.exchange()方法
线程1调用exchanger.exchange()方法,Exchanger阻塞线程1
线程2调用exchanger.exchange()方法,Exchanger阻塞线程2
交换数值
线程1和线程2继续执行