多线程同步
模拟卖票系统
public class Ticket implements Runnable
{
//当前拥有的票数
private int num = 100;
public void run()
{
while(true)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
//输出卖票信息
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
public class TicketDemo {
public static void main(String[] args)
{
Ticket t = new Ticket();//创建一个线程任务对象。
//创建4个线程同时卖票
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
//启动线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
从运行结果,我们就可以看出我们4个售票窗口同时卖出了1号票,这显然是不合逻辑的,其实这个问题就是线程同步问题。不同的线程都对同一个数据进了操作这就容易导致数据错乱的问题,也就是线程不同步。
解决思路:将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程时不可以参与运算的。必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。
解决线程同步的两种典型法案
1.通过锁(Lock)对象的方式解决线程安全问题
在java中锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但有的锁可以允许多个线程并发访问共享资源,比如读写锁,后面我们会分析)。在Lock接口出现之前,java程序是靠synchronized关键字实现锁功能的,而JAVA SE5.0之后并发包中新增了Lock接口用来实现锁的功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁,缺点就是缺少像synchronized那样隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性,可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Ticket implements Runnable {
//创建锁对象
private Lock ticketLock = new ReentrantLock();
//当前拥有的票数
private int num = 100;
public void run() {
while (true) {
try {
ticketLock.lock();//获取锁
if (num > 0) {
Thread.sleep(10);//输出卖票信息System.out.println(Thread.currentThread().getName()+".....sale...."+num--); }
} else {
break;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();//出现异常就中断
} finally {
ticketLock.unlock();//释放锁
}
}
}
}
2.通过synchronized关键字的方式解决线程安全问题
从JAVA SE1.0开始,java中的每一个对象都有一个内部锁,如果一个方法使用synchronized关键字进行声明,那么这个对象将保护整个方法,也就是说调用该方法线程必须获得内部的对象锁。
class Ticket implements Runnable
{
private int num = 100;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
}