在java中使用对象锁定进行同步

时间:2011-01-03 10:43:28

标签: java concurrency object synchronization

我有两个线程thread1(打印号码)& thread2(打印字母)。 我的目标是通过同步化获得以下输出:

  

1   一个   2   b   3   C   4   d   五   ë

class thread1 implements Runnable {
    public void run() {

        try {

            for (int i = 1; i <= 5; i++) {
                System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                synchronized (Testing.class) {
                    System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));

                    try {
                        System.out.println(i);
                        Testing.class.notifyAll();
                        System.out.println("Thread1:Going to wait");
                        Testing.class.wait();
                        System.out.println("Thread1:Resuming from wait");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

            System.out.println("Finsihed thread1");


        } catch (Exception e) {
            System.out.println(e);
        }

    }
}



class thread2 implements Runnable {
    char[] alphabets = { 'a', 'b', 'c', 'd', 'e' };

    public void run() {

        try {

            for (int i = 0; i < 5; i++) {
                System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                synchronized (Testing.class) {
                    try {
                        System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                        System.out.println("Thread2:Going to wait");
                        Testing.class.wait();
                        System.out.println("Thread2:Resuming from wait");
                        System.out.println(alphabets[i]);
                        Testing.class.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }


        } catch (Exception e) {
            System.out.println(e);
        }

    }

}


    public class Testing {

        public static void main(String[] args) {
            Testing w= new Testing();
            thread1 t1 = new thread1();
            thread2 t2 = new thread2();
            Thread th1 = new Thread(t1, "");

            Thread th2 = new Thread(t2, "");
            try {
                th1.start();
                th2.start();
            } catch (Exception e) {
                System.out.println(e);
            }

        }
    }

我收到了输出:

  

Thread1是否持有锁   Testing.class:假

     

Thread1是否持有锁   Testing.class:真

     

1

     

线程1:要等待

     

Thread2是否持有锁   Testing.class:假

     

Thread2是否持有锁   Testing.class:真

     

线程2:要等待

如果thread2已被thread1锁定,那么thread2如何获得了Testing.class的锁定?此外,有没有其他优雅的方式来实现这种同步?提前谢谢。

5 个答案:

答案 0 :(得分:1)

详细了解Java Concurrency

调用wait会释放锁定。

答案 1 :(得分:1)

当您调用wait()方法时,您调用它的线程会暂时放弃锁定。因此,当thread1在wait()方法内等待时,它没有持有锁,而thread2可以获得锁。

wait()方法返回时,线程将再次保持锁定。

班级wait()Object方法的API文档详细说明了这一点。

答案 2 :(得分:0)

您遇到的基本问题是释放同步块,允许两个线程同时通过循环。这意味着任何一个线程都可以按任何顺序获取锁定。

AFAIK,最简单的解决方案是使用旗帜。

final int length = 10;
final AtomicBoolean flag = new AtomicBoolean();
new Thread(new Runnable() {
    public void run() {
        for (int i=1;i<=length;i++) {
            while(flag.get());
            System.out.print(i+" ");
            flag.set(true);
        }
    }
}).start();

new Thread(new Runnable() {
    public void run() {
        for (char c='a';c<'a'+length;c++) {
            while(!flag.get());
            System.out.print(c+" ");
            flag.set(false);
        }
       System.out.println();
    }
}).start();

同步完成此任务的最优雅方法是拥有一个线程。线程专门设计用于执行两个任务,它们之间尽可能不依赖。

顺便说一句

如果在调用wait()之前调用notifyAll(),则通知将丢失。 wait()将永远等待。

您创建一个丢弃的测试对象(将其删除)。

你捕获InterruptedException,你打印并继续,好像什么都没发生(即删除嵌套的catch)

答案 3 :(得分:0)

这是完整的工作代码

公共类MyClass

{

MyClass mClass;

public void doTest()

{

  final  int [] a = {1,2,3,4,5,6,7,8,9,10};
  final  char [] c = {'a','b','c','d','e','f','g','h','i','j'};
   mClass = this; 
   Thread t1 = new Thread(new Runnable(){

     public void run()
     {
        for(int i = 0 ; i<a.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(a[i]+" "); 
           mClass.notify();
           try{mClass.wait();}catch(Exception e){}

         }

        }

     }

   });    
   t1.start();
   Thread t2 = new Thread(new Runnable(){

     public void run()
     {
        for(int i = 0 ; i<c.length ; i++)
        {synchronized(mClass)
         {
           System.out.print(c[i]+" "); 
           mClass.notify();
             try{mClass.wait();}catch(Exception e){}
         }

        }

     }

   });    
   t2.start();

}    public static void main(String [] ar)     {

  new MyClass().doTest();
} 

}

答案 4 :(得分:0)

公共类MyClass {    MyClass mClass;    boolean isFirstStartedRunning = true;    public void doTest()    {       final int [] a = {1,2,3,4,5,6,7,8,9,10};       final char [] c = {'a','b','c','d','e','f','g','h','i','j'};        mClass = this;        线程t1 =新线程(新的Runnable(){

     public void run()
     {
        isFirstStartedRunning = false;
        for(int i = 0 ; i<a.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(a[i]+" "); 
           mClass.notify();
            if(i==a.length-1)return;

             try{mClass.wait();}catch(Exception e){}


         }

        }

     }

   });    
   t1.start();
   Thread t2 = new Thread(new Runnable(){

     public void run()
     {
        if(isFirstStartedRunning){
          try{mClass.wait();}catch(Exception e){}
        }
        for(int i = 0 ; i<c.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(c[i]+" "); 
           mClass.notify();
           if(i==a.length-1)return;
           try{mClass.wait();}catch(Exception e){}


         }

       }

     }

   });    
   t2.start();

}    public static void main(String [] ar)     {

  new MyClass().doTest();

} 

} 现在检查答案