锁
锁的设计
1.减少锁持有时间
减少锁的持有时间有助于降低锁冲突的可能性,进而提升系统的并发能力。
2.减小锁粒度
缩小锁定对象的范围,从而减少锁冲突的可能性,进而提高系统的并发能力。
3.读写分离锁
在读多,写少的环境下用读写锁能大大减少线程等待时间。
4.锁粗化
在遇到一连串地对同一锁不断进行请求和释放的操作时,把所有的锁操作整合成对锁的一次请求,从而减少对锁的请求同步次数。
虚拟机对锁的优化
1.锁偏向
如果一个线程获得了锁,那么锁就进入偏向模式,当这个线程再次请求锁时,无须再做任何同步操作。
2.轻量级锁
3.自旋锁
4.锁消除
无锁
使用无锁的方式完全没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销,因此,它比基于锁的方式拥有更优越的性能
比较交换(CAS)
它包含三个参数CAS(V,E,N) ,V表示要更新的变量,E表示预期值,N表示新值。仅当V值等于E值时,才会将V值设为N,如果V值和E值不同则说明有其它线程做了更新,则当前线程什么也不做。
AtomicInteger
直接使用CAS操作的线程安全类型
AtomicLong,AtomicBoolean,AtomicReference类似;
private static AtomicInteger atomicInteger=new AtomicInteger();
private static CountDownLatch countDownLatch=new CountDownLatch(10);
public static void main(String[] args) {
ExecutorService executorService=Executors.newFixedThreadPool(10);
for (int i = 0 ; i < 10 ; i ++) {
executorService.submit(
()->{
for(int k = 0 ; k < 10000 ; k ++) {
atomicInteger.incrementAndGet();
}
countDownLatch.countDown();
}
);
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger);
}
AtomicStampedReference
//加入时间戳的CAS对象引用操作,可能解决由于线程修改n次后值不变的bug问题
private static AtomicStampedReference<Integer> reference=new AtomicStampedReference<>(19, 0);
public static void main(String[] args) {
for (int i=0; i < 3; i++) {
int stamp=reference.getStamp();
new Thread(
() -> {
while (true) {
while (true) {
Integer money=TestAtomicStamped.reference.getReference();
if (money < 20) {
if (reference.compareAndSet(money, money + 20, stamp, stamp + 1)) {
System.out.println(" 充值20成功,余额 =" + reference.getReference());
break;
}
} else {
System.out.println(" 余额大于20,无须充值");
break;
}
}
}
}
).start();
}
for (int i=0; i < 3; i++) {
new Thread(
() -> {
while (true) {
int stamp=reference.getStamp();
Integer money=TestAtomicStamped.reference.getReference();
if (money > 10) {
if (reference.compareAndSet(money, money - 10, stamp, stamp + 1)) {
System.out.println(" 消费10,余额 = " + reference.getReference());
break;
}
} else {
System.out.println(" 余额不足,请充值");
break;
}
}
}
).start();
}
}
充值20成功,余额 =39
余额大于20,无须充值
余额大于20,无须充值
余额大于20,无须充值
消费10,余额 = 29
消费10,余额 = 19
消费10,余额 = 9
余额不足,请充值
死锁
互相占用对方的请求的锁资源,造成线程blocking
private static Object lock1 = new Object() ;
private static Object lock2 = new Object() ;
public static void main(String[] args) {
new Thread(
()->{
synchronized (lock1){
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " lock1");
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + " lock2");
}
}
}
).start();
new Thread(
()->{
synchronized (lock2){
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " lock2");
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + " lock1");
}
}
}
).start();
}
Thread-1 lock2
Thread-0 lock1