日期:2014-05-20  浏览次数:20787 次

java同步机制
java中的同步在用起来感觉很简单,但是内部深层的机制是怎么样的呢?就是涉及到“监视器”、“锁”、“对象锁”这些概念的那些知识,能不能详细的解释一下同步的工作原理和流程。
另外,书上说,通过实现Runnable接口来创建多线程能够实现资源共享,以下是一个卖票程序:
Java code

class Myrunnable implements Runnable{
    private int ticket=5;
    public void run(){
    for(int i=0;i<100;i++){
      if(ticket>0){
        try{
          Thread.sleep(300);
        }catch(InterruptedException e){
          e.printStackTrace();
        }
        System.out.println("ticket="+ticket--);
      }
    }
  }
}
public class Demo{
    public static void main(String[] args){
      MyRunnable myr=New MyRunnable();
      Thread t1=New Thread(myr);
      Thread t2=New Thread(myr);
      Thread t3=New Thread(myr);
      t1.start();
      t2.start();
      t3.start();
    }
}


程序中加入延迟,会出现票为负数情况,反映出三个线程共享资源,这是不是因为在创建线程时向Thread构造函数中传入的是同一个引用的缘故啊?如果我建立三个Myrunnable的实例,然后传入三个线程的构造函数中,是不是就不会有资源共享了?

------解决方案--------------------
理论部分就让别人来回答吧,我来回答你举的例子

Java code

class MyRunnable implements Runnable
{
    private int ticket=5;
    
    public void run()
    {
        for(int i=0;i<100;i++)
        {
            synchronized(this)    //判断ticket前先将该对象锁住,防止当ticket=1时三个线程又同时减1将ticket变为负数
            {
                if(ticket>0)
                {
                    try
                    {
                        Thread.sleep(300);
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    System.out.println("ticket="+ticket--);
                }
            }
        }
    }
}

public class Demo
{
    public static void main(String[] args)
    {
        MyRunnable myr=new MyRunnable();
        Thread t1=new Thread(myr);
        Thread t2=new Thread(myr);
        Thread t3=new Thread(myr);
        t1.start();
        t2.start();
        t3.start();
    }
}

------解决方案--------------------
如果我建立三个Myrunnable的实例,然后传入三个线程的构造函数中,是不是就不会有资源共享了?

什么是共享资源?

在本例中,因为只有一个Myrunnable的实例,因此就只有一个private int ticket=5;也就是说3个线程会同时访问ticket这个成员变量,因此,ticket就是共享资源

如果有三个Myrunnable的实例,每一个线程一个实例,当然就不存在共享资源这个说法了,就不会发生线程安全问题了。

------解决方案--------------------
嗯,我和楼主在看同一本书。我想借机问一下,如果是多个Myrunnable接口的实例,将ticket设置为static作为共享数据可以吗?
------解决方案--------------------
探讨

嗯,我和楼主在看同一本书。我想借机问一下,如果是多个Myrunnable接口的实例,将ticket设置为static作为共享数据可以吗?

------解决方案--------------------
探讨
将ticket设置为static作为共享数据,就需要做同步,否则就会出现线程安全问题
synchronized(Myrunnable.class){}