两者区别
Sychronized | Lock | |
类型 | java的一个关键字,也就是说java语言内置的特性,wait 、notify、notifyAll | java.util.concurrent.locks包下常用的类,可以使用Condition进行线程之间的调度, |
锁的释放 | 会自动释放锁(1.执行完同步代码块会释放锁,2线程执行过程中发生异常会释放锁,不会出现死锁) | 需要在finally中手工释放lock.unlock(),否则容易造成线程死锁,使用时记住try catch |
使用特性 | 可重入\不可中断\非公平 | 可重入\可中断(interrupt)\可公平(也可非公平) |
获取锁的状态 | 不能知道有没有获取锁 | 可以通过trylock来知晓是否获取到了锁 |
Sychronized原理
采用的是CPU悲观锁机制,线程获得的是独占锁,其他线程只能依靠阻塞来等待线程释放锁
1.5之前是低效的,1.6之后优化可以适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等
Lock原理
采用的乐观锁机制. 乐观锁实现的机制就是CAS操作(Compare and Swap) 判断值是否与预期值
三个线程循环打印abc
java多线程编程之连续打印abc的几种解法 - 平凡希 - 博客园 (cnblogs.com)
public class Lockprinter {
//状态变量
private volatile int state = 0;
private class Printer implements Runnable {
private static final int PRINT_COUNT = 10;
//打印锁
private final Object printLock;
//打印标志位 和state关联
private final int printFlag;
//后继线程的打印标志位 state变量相关
private final int nextPrintFlag;
//该线程的打印字符
private final char printChar;
public Printer(Object printLock, int printFlag, int nextPrintFlag, char printChar) {
super();
this.printLock = printLock;
this.printFlag = printFlag;
this.nextPrintFlag = nextPrintFlag;
this.printChar = printChar;
}
@override
public void run() {
//获取打印锁 进入临界区
synchronized (printLock) {
//连续打印PRINT_COUNT
for (int i = 0; i < PRINT_COUNT; i++) {
//循环检验标志位,每次都阻塞然后等待唤醒
while (state != printFlag) {
try {
printLock.wait();
} catch (InterruptedException e) {
return;
}
}
//打印字符
System.out.println(printChar);
//设置状态变量为下一个线程的标志位
state = nextPrintFlag;
//注意要notifyAll,不然会死锁,因为notify只通知一个
//但是同时等待的是两个, 如果唤醒的是不正确的那个就会没人唤醒,死锁了
printLock.notifyAll();
}
}
}
}
public void test() throws InterruptedException{
//锁
Object lock = new Object();
//打印a的线程
Thread threadA = new Thread(new Printer(lock,0,1,'A'));
//打印b的线程
Thread threadB = new Thread(new Printer(lock,1,2,'B'));
//打印c的线程
Thread threadC = new Thread(new Printer(lock,2,0,'C'));
//一次启动ABC 线程
threadA.start();
Thread.sleep(100);
threadB.start();
Thread.sleep(100);
threadC.start();
}
public static void main(String[] args) throws InterruptedException {
Lockprinter print = new Lockprinter();
print.test();
}
}
}