Synchronized和lock的区别
- synchronized属于JVM层面,属于java的关键字
- 底层使用jvm 字节码指令monitorenter(通过monitor对象来完成,wait/notify方法也依赖monitor对象,只能在同步块或方法中才能使用wait/notify方法)
- lock属于具体类 juc中的Lock接口的实现类
使用方法
- synchronized: 不需要用户去手动释放,当synchronized代码执行后,系统会自动让线程释放对锁的占用
- ReentrantLock: 需要手动释放锁,如果没有主动释放锁,可能会出现死锁现象,如果使用lock和unlock操作
是否可中断
- synchronized: 不可中断 除非方法执行完成或者异常退出
- ReentrantLock: 可中断 可以设置超时方法
- trylock(long timeout,TimeUnit unit)
- lockInterrupible 可以使用interrupt方法中断
是否公平
- synchronized: 非公平锁
- ReentrantLock: 默认非公平锁,也可以通过构造函数传入true 改为公平锁
绑定多条件condition
- synchronized: 不支持condition 要么随机唤醒 要么全部唤醒
- ReentrantLock: 用来实现分组唤醒需要唤醒的线程,可以准确唤醒
使用condition来实现精准唤醒
题目:多线程之间按顺序调用,实现 A-> B -> C 三个线程启动,要求如下:
AA打印5次,BB打印10次,CC打印15次
紧接着
AA打印5次,BB打印10次,CC打印15次
..
来10轮
package com.corn.juc.demo;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author : Jim Wu
* @version 1.0
* @function :
* <p>
* 题目:多线程之间按顺序调用,实现 A-> B -> C 三个线程启动,要求如下:
* AA打印5次,BB打印10次,CC打印15次
* 紧接着
* AA打印5次,BB打印10次,CC打印15次
* ..
* 来10轮
* @since : 2020/12/31 17:41
*/
public class LockConditionDemo {
// 1->A线程 2->B线程 3->C线程
private volatile int threadNo = 1;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
Condition condition4 = lock.newCondition();
AtomicInteger num = new AtomicInteger();
private void printNumber(int time, Condition condition) throws Exception {
try {
lock.lock();
while (threadNo != 1 && condition == condition1) {
condition1.await();
}
while (threadNo != 2 && condition == condition2) {
condition2.await();
}
while (threadNo != 3 && condition == condition3) {
condition3.await();
}
while (threadNo != 4 && condition == condition4) {
condition4.await();
}
if (time != 0) {
for (int i = 0; i < time; i++) {
System.out.println(Thread.currentThread().getName() + "\t" + num.incrementAndGet());
}
} else {
System.out.println();
System.out.println();
}
if (time == 5) {
threadNo = 2;
condition2.signal();
} else if (time == 10) {
threadNo = 3;
condition3.signal();
} else if (time == 15) {
threadNo = 4;
condition4.signal();
} else {
threadNo = 1;
condition1.signal();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
LockConditionDemo demo = new LockConditionDemo();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
demo.printNumber(5, demo.condition1);
} catch (Exception e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
try {
demo.printNumber(10, demo.condition2);
} catch (Exception e) {
e.printStackTrace();
}
}, "B").start();
new Thread(() -> {
try {
demo.printNumber(15, demo.condition3);
} catch (Exception e) {
e.printStackTrace();
}
}, "C").start();
new Thread(() -> {
try {
demo.printNumber(0, demo.condition4);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}