Java线程同步(synchronized)——卖票问题
卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题。
Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1,当某个线程执行了synchronized(object)语句后,object对象的标志位变为0状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态。
当一个线程执行到synchronized(object)语句的时候,先检查object对象的标志位,如果为0状态,表明已经有另外的线程正在执行synchronized包括的代码,那么这个线程将暂时阻塞,让出cpu资源,直到另外的线程执行完相关的同步代码,并将object对象的标志位变为1状态,这个线程等阻塞就取消,线程能继续运行,该线程又将object的标志位变为0状态,防止其他的线程再进入相关的同步代码块中。
所以在代码中,对共享资源采用synchronized关键字,可以实现线程同步。
代码如下:
package luxl; public class ThreadSynchronizationTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub TicketSeller seller = new TicketSeller(); Thread t1 = new Thread(seller); Thread t2 = new Thread(seller); Thread t3 = new Thread(seller); t1.start(); t2.start(); t3.start(); } } /** * * @author Administrator * */ class TicketSeller implements Runnable{ int ticket_num = 100; @Override public void run() { // TODO Auto-generated method stub while(true){ synchronized(this){ if(ticket_num > 0){ try{ Thread.sleep((int)Math.random()*2000); }catch(Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is sell the ticket " + ticket_num); ticket_num --; } } } } }
上面的代码是创建了一个TicketSeller对象,然后创建不同的线程,所以这里是通过synchronized(this)中的this对象来实现的互锁。如果是通过不同的runnable对象创建线程,仍要实现线程同步对某一个资源实现线程同步,可以在runnable对象中创建一个静态的object类成员变量A,通过synchronized(A)也可以实现线程同步。同样的,也可以通过将访问共享资源的类静态方法进行synchronized修饰,也可以实现线程同步。