多线程实现同步机制的方式有3种

1.synchronized作用在方法上

弊端:方法上面的锁是this,如果两个线程的实例不是一个,不能锁住

2.synchronized作用在代码块的方式

3.Lock的实现(ReentrantLock)的作用在任意代码

与synchronized的区别是synchronized是隐式锁,不需要明确声明锁打开与关闭
ReentrantLock是显示锁,需要自己打开锁的范围,自己关掉锁的范围

以下代码中有使用Callable的方式创建线程的,因为FutureTask有CAS的线程安全机制,它本身可以解决线程安全的问题

代码实现:

package com.example.demo.juc;

import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
TicketR ticketR = new TicketR();
// Ticket ticket = new Ticket();
//FutureTask本身利用了CAS实现了线程安全
// FutureTask<Object> futureTask = new FutureTask<Object>(ticket);
//
// new Thread(futureTask,"1号窗口").start();
// new Thread(futureTask,"2号窗口").start();
// new Thread(futureTask,"3号窗口").start();



//
new Thread(ticketR,"1号窗口").start();
new Thread(ticketR,"2号窗口").start();
new Thread(ticketR,"3号窗口").start();
}
}

class Ticket implements Callable {

private int ticket = 100;

@Override
public Object call() throws Exception {
while(true) {
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ": 余票为: " + --ticket);
}
}
}
}

class TicketR implements Runnable {

private int ticket = 100;

private Lock lock = new ReentrantLock();

@Override
public void run() {
while(true) {
try {
lock.lock();
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ": 余票为: " + --ticket);
}
}finally {
lock.unlock();
}
}
}
}