Synchronized 和 Lock的区别
1.Synchronized是java内置的关键字 , Lock是一个java类
2.Synchronized无法获取锁的状态 , Lock可以判断是否活得锁
3.Synchronized代码执行完立即释放锁, Lock需要手动开关,不释放就会死锁
4.Synchronized可重入锁,不可以中断,非公平 , Lock, 可重入锁,可以判断锁,公平性可以自己设置
5.Synchronized如果某个线程获得锁后被阻塞,那Synchronized的另一个线程就会一直处于等待状态,Lock锁加锁的两个线程不会生生这种死锁
唤醒方式
Synchronized {
//阻塞
this.wait
//唤醒
this.notify() || this.nitifyAll();
}
Lock {
//加锁
lock.lock();
//释放锁
lock.unlock();//一般加在finally中 , try中处理事务
//监视器
CCondition condition = lock.newCondition();
//通过监视器阻塞和唤醒
//阻塞
condition.await();
//唤醒
condition.signal(); || condition.signalAll();
}
生产者消费者问题的实现
传统Synchronized实现
以下的线程均放在(lamda表达式中)
package com.cxy.javathread.myself;
public class A {
public static void main(String[] args) {
th th = new th();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.incred();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.decred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.incred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.decred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class th{
int num = 0;
public synchronized void incred() throws InterruptedException {
if (num!=0){
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName()+"->"+num);
this.notifyAll();
}
public synchronized void decred() throws InterruptedException {
if(num==0){
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+"->"+num);
this.notifyAll();
}
}
运行发现上述代码有一个问题
虚假唤醒现象
A->1
B->0
A->1
B->0
A->1
B->0
A->1
B->0
A->1
B->0
A->1
B->0
C->1
B->0
A->1
B->0
C->1
B->0
A->1
B->0
C->1
D->0
C->1
A->2
C->3
D->2
D->1
D->0
C->1
A->2
C->3
D->2
D->1
D->0
C->1
D->0
C->1
D->0
C->1
D->0
Process finished with exit code 0
当只有两个线程在相互唤醒的过程中 , 两个线程交替打印 , 但是当线程多了以后,会发生虚假唤醒现象
所以需要吧 if 换成 while
if(num!=0){
this.wait();
}
//换成
while(num!=0){
this.wait();
}
package com.cxy.javathread.myself;
public class A {
public static void main(String[] args) {
th th = new th();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.incred();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.decred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.incred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
th.decred();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class th{
int num = 0;
public synchronized void incred() throws InterruptedException {
if (num!=0){
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName()+"->"+num);
this.notifyAll();
}
public synchronized void decred() throws InterruptedException {
if(num==0){
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+"->"+num);
this.notifyAll();
}
}
发现结果正确
//发现结果没用任何问题
A->1
B->0
A->1
B->0
A->1
B->0
A->1
B->0
C->1
B->0
A->1
B->0
C->1
B->0
A->1
D->0
C->1
B->0
A->1
D->0
C->1
B->0
A->1
D->0
C->1
B->0
A->1
D->0
C->1
D->0
A->1
D->0
C->1
D->0
C->1
D->0
C->1
D->0
C->1
D->0
Process finished with exit code 0
Lock锁
Lock锁使用Condition作为监视器来完成唤醒与阻塞
package com.cxy.javathread.myself;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class B {
public static void main(String[] args) {
th2 th = new th2();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.incred();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.decred();;
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.incred();;
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.decred();;
}
},"D").start();
}
}
class th2{
int num = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void incred(){
lock.lock();
try {
while (num!=0){
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName()+"->"+num);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decred(){
lock.lock();
try {
while(num==0){
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName()+"->"+num);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
精确唤醒的Lock锁
package com.cxy.javathread.myself;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class C {
public static void main(String[] args) {
th3 th = new th3();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
th.printC();
}
},"C").start();
}
}
class th3{
private int num = 1;
private Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void printA(){
lock.lock();
try {
//事务
while(num!=1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"--->aaa--->"+num);
num = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
//事务
while(num!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"--->bbb--->"+num);
num = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
//事务
while(num!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"--->ccc--->"+num);
num = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
运行结果
交替打印
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
A--->aaa--->1
B--->bbb--->2
C--->ccc--->3
Process finished with exit code 0