Lock(ReentrantLock)实现线程同步,线程安全
原创
©著作权归作者所有:来自51CTO博客作者DeBuggggggg的原创作品,请联系作者获取转载授权,否则将追究法律责任
多线程实现同步机制的方式有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();
}
}
}
}