文章目录
一、多线程同步
二、线程安全
三、同步代码块
四、同步方法
五、线程安全类
六、同步锁
七、
一、多线程同步
- 多线程的并发执行可以提高程序的效率,但是,当多个线程去访问同一个资源时,也会引发一些安全问题。
- eg:当统计一个班级的学生数目时,进进出出难统计。
- 为了解决这样的问题,需要实现多线程的同步,即限制某个资源在同一时刻只能被一个线程访问。
二、线程安全
- eg:售票案例,极有可能碰到“意外”情况,如一张票被打印多次,或者打印出的票号为0甚至负数。
- 这些“意外”是由多线程操作共享资源tickets所导致的线程安全问题。
三、同步代码块解决数据安全问题
- 了解到线程安全问题其实就是由多个线程同时处理共享资源所导致的。
- Java中提供了线程同步机制,当多个线程使用同一个共享资源时,可以处理共享资源代码放置在一个使用synchronize关键字来修饰的代码块中,这段代码叫同步代码块。
同步代码块:
public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();
public void run() {
while(true) {
synchronized (obj) {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
四、同步方法解决数据安全问题
private int tickets = 100;
private Object obj = new Object();
public void run() {
while(true) {
saleTicket();
}
}
private synchronized void saleTicket() {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
五、线程安全类
六、同步锁
- 同步代码块和同步方法使用一种封闭式的锁机制,但是有一些限制,无法中断一个正在等候获得锁的进程,也无法轮询得到锁,如果不想等了,也就没锁了。
- 从JDK5开始,Java增加了一个功能更加强大的Lock锁,优势在于Lock锁可以让某个线程在持续获取同步锁失败后返回,不再继续等待,更加灵活。
- ReentrantLock类是Lock锁接口的实现类,也是常用的同步锁,在该同步锁中有lock()方法和unlock()方法。
- 为了保证所有情况下都能正常解锁以确保其他线程可以执行,会在finally代码块中调用unlock()方法来解锁。
Lock中提供了获得锁和释放锁的方法:
- lock():获得锁
- unlock():释放锁
- Lock是接口不能直接实例化,这里采用它是实现类ReentrantLock来实例化
- ReentrantLock():创建一个ReentrantLock的实例
private int tickets = 100;
private Lock lock = new ReentrantLock();
public void run() {
while(true) {
try {
lock.lock();
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}finally {
lock.unlock();
}
}
}