1,synchronized是内置的Java关键字;Lock是一个Java类
2,synchronized无法判断获取锁的状态;Lock可以判断
3,synchronized会自动释放锁;Lock必须要手动加锁和释放锁(可能会遇到死锁)
4,synchronized:线程1(获得锁->阻塞)、线程2(等待);Lock不一定会一直等待下去,Lock会有一个trylock去尝试获取锁,不会造成长久的等待
5,synchronized是可重入锁,不可以中断的,非公平的;Lock,可重入的,可以判断锁,可以自己设置公平锁和非公平锁
6,synchronized适合锁少量的代码同步问题;Lock适合锁大量的同步代码
卖票例子
1,synchronized
/**
* 真正的多线程开发
* 线程就是一个单独的资源类,没有任何的附属操作!
*/
public class SaleTicketDemo01 {
public static void main(String[] args) {
//多线程操作
//并发:多线程操作同一个资源类,把资源类丢入线程
Ticket ticket = new Ticket();
//@FunctionalInterface 函数式接口 jdk1.8之后 lambda表达式
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"A").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"B").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"C").start();
}
}
//资源类
//属性+方法
//oop
class Ticket{
private int number=50;
//卖票的方式
// synchronized 本质:队列,锁
public synchronized void sale(){
if(number>0){
System.out.println(Thread.currentThread().getName()+" 卖出了第"+number+" 张票,剩余:"+number+" 张票");
number--;
}
}
}
2,lock
public class SaleTicketDemo02 {
public static void main(String[] args) {
//多线程操作
//并发:多线程操作同一个资源类,把资源类丢入线程
Ticket2 ticket = new Ticket2();
new Thread(()->{for(int i=0;i<40;i++) ticket.sale(); },"A").start();
new Thread(()->{for(int i=0;i<40;i++) ticket.sale(); },"B").start();
new Thread(()->{for(int i=0;i<40;i++) ticket.sale(); },"C").start();
}
}
//lock三部曲
//1、 Lock lock=new ReentrantLock();
//2、 lock.lock() 加锁
//3、 finally=> 解锁:lock.unlock();
class Ticket2{
private int number=50;
Lock lock=new ReentrantLock();
//卖票的方式
// 使用Lock 锁
public void sale(){
//加锁
lock.lock();
try {
//业务代码
if(number>=0){
System.out.println(Thread.currentThread().getName()+" 卖出了第"+number+" 张票,剩余:"+number+" 张票");
number--;
}
}catch (Exception e) {
e.printStackTrace();
}
finally {
//解锁
lock.unlock();
}
}
}
等待唤醒机制
多个线程交替打印1,0
1,synchronized
package com.llb.juc.producerAndCunsumer;
class Data{
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
//使用while防止虚假唤醒
while (number!=0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+" number : "+number);
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number != 1){
this.wait();
}
number --;
System.out.println(Thread.currentThread().getName()+" number : "+number);
this.notifyAll();
}
}
public class DemoSynchronized {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
try {
for (int i = 0; i < 5; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "AA").start();
new Thread(()->{
try {
for (int i = 0; i < 5; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "BB").start();
new Thread(()->{
try {
for (int i = 0; i < 5; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "CC").start();
new Thread(()->{
try {
for (int i = 0; i < 5; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "DD").start();
}
}
2,lock
package com.llb.juc.producerAndCunsumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Data2{
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//+1
public void increment(){
lock.lock();
try {
//使用while防止虚假唤醒
while (number!=0){
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+" number : "+number);
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//-1
public void decrement(){
lock.lock();
try {
//使用while防止虚假唤醒
while (number!=1){
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+" number : "+number);
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class DemoLock {
public static void main(String[] args) {
Data2 data2 = new Data2();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data2.increment();
}
}, "AA").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data2.decrement();
}
}, "BB").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data2.increment();
}
}, "CC").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data2.decrement();
}
}, "DD").start();
}
}
精确唤醒指定线程用Condition
package com.llb.juc.producerAndCunsumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Data3{
Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
private int number = 0;
private int num = 1;
// private String sign = "A";
public void printA(){
lock.lock();
try {
while (num!=1){
c1.await();
}
System.out.println(Thread.currentThread().getName()+" : A : "+number);
number++;
num=2;
c2.signal();
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (num!=2){
c2.await();
}
System.out.println(Thread.currentThread().getName()+" : B : "+number);
number++;
num=3;
c3.signal();
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (num!=3){
c3.await();
}
System.out.println(Thread.currentThread().getName()+" : C : "+number);
number++;
num=1;
c1.signal();
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class DemoCondition {
public static void main(String[] args) {
Data3 data3 = new Data3();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data3.printA();
}
}, "AA").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data3.printB();
}
}, "BB").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data3.printC();
}
}, "CC").start();
}
}