锁
- 同步关键字
— 自旋锁: 为了不放弃cpu执行时间,循环使用cas技术对数据尝试更新,直至成功.
— 悲观锁: 假定会发生并发冲突,同步所有数据的相关操作,从读数据就开始上锁.
— 乐观锁: 假定没有冲突,在修改数据是如果发现数据和之前获取的不一致,则读取最新的数据,修改后重试修改.
— 独享锁: 给资源加上写锁,线程可以修改资源,其他线程不能再加锁.(单写)
— 共享锁: 给资源加上读锁只能读,其他线程也只能加读锁,不能加写锁.(多读)
— 可重入锁: 拿到锁后可以自由的进入同一把锁同步的代码
— 不可重入锁:
— 公平锁:争抢锁的执行顺序
— 不公平锁:
synchronized
- 是悲观锁
- 独享锁
- 可重入锁
锁粗化
- 运行时jit编译优化
锁消除
- jit运行时会把锁去掉StringBuffer的append方法
Lock接口
package com.yulang.threadpool.thread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private volatile LongAdder i=new LongAdder();
private int j = 0;
private Lock lock = new ReentrantLock();
public synchronized void add(){
try{
lock.lock();
j++;
}finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
LockTest lockTest = new LockTest();
for(int j=0;j<2;j++){
new Thread(()->{
for(int i=0;i<10000;i++){
lockTest.add();
}
}).start();
}
TimeUnit.SECONDS.sleep(2);
System.out.println(lockTest.j);
}
}
lock锁是可重入锁
注意解锁次数一定要和锁定次数相同
package com.yulang.threadpool.thread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private volatile LongAdder i=new LongAdder();
private int j = 0;
private Lock lock = new ReentrantLock();
public void add(){
try{
lock.lock();
add2();
j++;
}finally {
lock.unlock();
}
}
public void add2(){
try{
lock.lock();
j++;
}finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
LockTest lockTest = new LockTest();
for(int j=0;j<2;j++){
new Thread(()->{
for(int i=0;i<10000;i++){
lockTest.add();
}
}).start();
}
TimeUnit.SECONDS.sleep(2);
System.out.println(lockTest.j);
}
}
hashmap是线程不安全的,可以使用hashtable
读写锁
package com.yulang.threadpool.thread;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockSynchronized {
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void read(){
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "读操作!");
}
public void write(){
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName()+"写操作!");
}
public static void main(String[] args) {
LockSynchronized lockSynchronized = new LockSynchronized();
new Thread(()->{
while (true)
lockSynchronized.write();
}).start();
new Thread(()->{
while (true)
lockSynchronized.write();
}).start();
/*while (true){
new Thread(()->{
lockSynchronized.write();
}).start();
}*/
}
}
缓存降级