这是我参与 8 月更文挑战的第 10 天,活动详情查看: 8月更文挑战
1.Java锁之自旋锁
自旋锁:spinlock,是尝试获取锁的线程不会立即阻塞,而是采用循环的方式去获取获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU
自旋锁的实现的代码:
package JUC;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @Author MingJian_Zhu
* @Date 2021/8/13 9:27
*/
public class SpinLockDemo {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "\t come in ");
while(!atomicReference.compareAndSet(null,thread)){
}
}
public void myUnLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
System.out.println(Thread.currentThread().getName() + "\t invoke myUnlock");
}
public static void main(String[] args) {
SpinLockDemo spinLockDemo = new SpinLockDemo();
new Thread(()->{
spinLockDemo.myLock();
try{
TimeUnit.SECONDS.sleep(5);
}catch(InterruptedException e){
e.printStackTrace();
}
spinLockDemo.myUnLock();
},"t1").start();
try{
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e){
e.printStackTrace();
}
new Thread(()->{
spinLockDemo.myLock();
spinLockDemo.myUnLock();
},"t2").start();
}
}
2 独占锁(写锁)/共享锁(读锁)/互斥锁
2.1 独占锁
指该锁一次只能被一个线程所持有。对ReentrantLock和Synchronized而言都是独占锁。
2.2 共享锁
指该锁可以被多个线程锁持有
对ReentrantReadWriteLock其读锁是共享,其写锁是独占
写的时候只能一个写,但是读的时候,可以多个人同时读
2.3 为什么会有写锁和读锁
原来我们使用ReentranLock创建锁的时候,是独占锁,也就是说一次只能一个线程访问,但是一个读写分离场景,读的时候想同时进行,因此原来独占锁的并发性就没这么好了,因为读锁并不会造成数据不一致的问题,因此可以多个人共享读。
多个线程同时读一个资源类没有任何问题,所以未了满足并发量,读取共享资源应该可以同时进行,但是如果一个线程想去写共享资源,就不应该再其有线程可以对该资源进行读或写
Ps:
-
读-读:能共存 -
读-写:不能共存 -
写-写:不能共存
实现代码:
package JUC;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @Author MingJian_Zhu
* @Date 2021/8/13 11:29
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for(int i = 0; i < 5; i++){
final int tempInt = i;
new Thread(()->{
myCache.put(tempInt + "",tempInt + "");
},String.valueOf(i)).start();
}
for(int i = 0; i < 5; i++){
final int tempInt = i;
new Thread(()->{
myCache.get(tempInt + "");
},String.valueOf(i)).start();
}
}
}
class MyCache {
private volatile Map<String, Object> map = new HashMap<>();
// private Lock lock = null;
/**
* 定义写操作
* 满足:原子 + 独占
* @param key
* @param value
*/
public void put(String key, Object value) {
System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key);
try {
// 模拟网络拥堵,延迟0.3秒
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成");
}
public void get(String key) {
System.out.println(Thread.currentThread().getName() + "\t 正在读取:");
try {
// 模拟网络拥堵,延迟0.3秒
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object value = map.get(key);
System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value);
}
}
\