
- 一、Java 锁
- 1.1、公平锁和非公平锁
- 1.2、可重入锁(递归锁)原理
- 1.3、自旋锁(spinlock)
- 1.3、读写锁
解释
公平锁解释:多线程情况下,按照申请锁的顺序进行获取锁,先来先得。
非公平锁解释:多线程情况下,获取锁的顺序不是按照申请锁顺序来的。高并发情况下,可能会导致优先级反转或者饥饿现象。
两者区别
公平锁是并发环境下,每个线程获取锁,查看等待队列,如果为空,或线程是等待队列的第一个,则占有锁,否则加入等待队列,按照先进先出规则队列中取到自己。
非公平锁就是上来直接占有锁,尝试失败,在采用公平锁方式。
JAVA 锁
ReentrantLock 属于非公平锁,可以通过构造函数 Booleen值指定,True 公平锁,False 非公平锁。非公平锁优点在于吞吐量比公平锁大
synchronized 也是非公平锁
1.2、可重入锁(递归锁)原理可重入锁 最大作用是避免死锁
package com.xin;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReenterLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
System.out.println("================synchronized================");
new Thread(() -> {
phone.sendQQ();
}, "t1").start();
new Thread(() -> {
phone.sendQQ();
}, "t2").start();
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
System.out.println("================ReentrantLock================");
Thread t3 = new Thread(phone,"t3");
Thread t4 = new Thread(phone,"t4");
t3.start();
t4.start();
}
}
class Phone implements Runnable{
public synchronized void sendQQ() {
System.out.println(Thread.currentThread().getName() + "t invoke:sendQQ");
sendWeChat();
}
public synchronized void sendWeChat() {
System.out.println(Thread.currentThread().getName() + "t #####invoke:sendWeChat");
}
@Override
public void run() {
get();
}
Lock lock = new ReentrantLock();
public void get() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "t invoke:get");
set();
} finally {
lock.unlock();
}
}
public void set() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "t invoke:set");
} finally {
lock.unlock();
}
}
}
1.3、自旋锁(spinlock)
理论
获取线程的锁不会被阻塞,线程会采用循环的方式获取锁,好处减少上下文切换资源浪费,缺点是循环消耗CPU。
代码
package com.xin;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class SpinlockDemo {
AtomicReference
1.3、读写锁
理论
独占锁(写锁):synchronized、ReentrantLock
共享锁(读锁):
互斥锁:ReadWriteLock
代码
读写锁代码
ReentrantReadWriteLock
package com.xin;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 1; i <= 5; i++) {
final int ii = i;
new Thread(() -> {
myCache.set(ii + "", ii + "");
myCache.get(ii + "");
}, String.valueOf(i)).start();
}
}
}
class MyCache {
private volatile Map map = new HashMap<>();
ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
public void get(String key) {
reentrantReadWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "t 进行读取");
TimeUnit.MILLISECONDS.sleep(300);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "t 读取值:" + o);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantReadWriteLock.readLock().unlock();
}
}
public void set(String key, Object value) {
reentrantReadWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "t 进行写入" + value.toString());
TimeUnit.MILLISECONDS.sleep(300);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "t 写入成功");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)