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修饰,也可以实现线程同步。

原文地址:https://www.cnblogs.com/ScorchingSun/p/3791048.html