ReentrantLock lock = new ReentrantLock(true);
Synchronized也是一种非公平锁。
指同一线程在外层方法获取锁的时候,在内层方法会自动获取锁。
ReentrantLock和Synchronized是典型的可重入锁
可重入锁最大的作用是避免死锁。
是指尝试获取锁的线程不会阻塞,而是采用循环的方式获取锁
public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var4));
return var5;
}
public class SpinLockDemo {
//原子引用线程
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public void myLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "\t comeIn");
while (!atomicReference.compareAndSet(null, thread)) {
}
}
public void myUnLock() {
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread, null);
System.out.println(Thread.currentThread().getName() + "\t 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(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
spinLockDemo.myLock();
spinLockDemo.myUnLock();
}, "t2").start();
}
}
对ReentrantWriteReadLock其读锁是共享锁,其写锁是独占锁,写写,读写,写读过程都是互斥的。也就是多线程下读的时候不写,写的时候不读,读的时候其他线程可以读。
class myCache {//资源类
private volatile Map<String, Object> map = new HashMap<>();
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void put(String key, Object value) {
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在写入:key:" + key);
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
}
public void get(String key) {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 开始读,key:" + key);
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + "\t 读完成,result:" + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
}
}
}
/**
* @author liujian
* @descripts 读写锁
* @create 2019-06-22 17:26
*
* 写操作:独占+原子,中间的过程必须是完整的统一体,不允许被打断,被分割
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
myCache myCache = new myCache();
for (int i = 0; i < 50; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.put(String.valueOf(tempInt), String.valueOf(tempInt));
}, String.valueOf(i)).start();
}
for (int i = 0; i < 50; i++) {
final int tempInt = i;
new Thread(() -> {
myCache.get(String.valueOf(tempInt));
}, String.valueOf(i)).start();
}
}
}
Synchronized是关键字,属于JVM层面。
Lock是具体的类(java.concurrent.locks.lock),是API层面的锁。
synchronized不可中断,只有抛出异常和运行完成两种情况。
ReentrantLock 可中断
Synchronized 是非公平锁
ReentrantLock 默认非公平锁,构建函数传入boolean值,true为公平锁,false为非公平锁。
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
Synchronized没有
ReentrantLock用来分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized要么唤醒一个线程要么唤醒全部线程。
题目:多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下:
AA打印五次,BB打印十次,CC打印15次
紧接着 AA打印五次,BB打印十次,CC打印15次
来10轮
public class SynAndReentrantLockDemo {
public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
for (int i = 0; i <10 ; i++) {
new Thread(() -> shareResource.print(5), "AA").start();
new Thread(() -> shareResource.print(10), "BB").start();
new Thread(() -> shareResource.print(15), "CC").start();
}
}
}
class ShareResource {
private int num = 1;
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void print(int j) {
lock.lock();
try {
if (j==5){
while (num != 1) {
c1.await();
}
for (int i = 0; i < j; i++) {
System.out.println(Thread.currentThread().getName() + "\t ");
}
num = 2;
c2.signal();
}else if (j==10){
while (num != 2) {
c2.await();
}
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "\t ");
}
c3.signal();
num = 3;
}else if (j==15){
while (num != 3) {
c3.await();
}
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName() + "\t ");
}
c1.signal();
num = 1;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}