java中使用对象锁进行同步

发布于 2024-10-10 06:18:24 字数 3011 浏览 2 评论 0原文

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

1 一个 2 乙 3 c 4 d 5

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 是否持有以下锁 测试.class?:false

Thread1 是否持有以下锁 测试.class?:true

1

线程1:等待

线程2是否持有锁 测试.class?:false

线程2是否持有锁 测试.class?:true

线程2:等待

当 Test.class 已被 thread1 锁定时,thread2 是如何获得该锁定的呢?另外,还有其他优雅的方式来实现这种同步吗?提前致谢。

I have two threads thread1(printing numbers) & thread2(printing alphabets).
My goal is to have the following output via syncronization:

1
a
2
b
3
c
4
d
5
e

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);
            }

        }
    }

I am getting the output:

Is Thread1 holding lock of
Testing.class?:false

Is Thread1 holding lock of
Testing.class?:true

1

Thread1:Going to wait

Is Thread2 holding lock of
Testing.class?:false

Is Thread2 holding lock of
Testing.class?:true

Thread2:Going to wait

How did thread2 got hold the lock of Testing.class when it was already locked by thread1?. Also, Is there any other elegant way to achieve this sync?. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

枕花眠 2024-10-17 06:18:24

详细了解 Java 并发

调用wait释放锁。

Read a bit more about Java Concurrency.

Calling wait releases the lock.

白云悠悠 2024-10-17 06:18:24

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

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

Object 类中的 wait() 方法的 API 文档详细解释了这一点。

When you call the wait() method, the thread that you call it in is temporarily giving up the lock. So while thread1 is waiting inside the wait() method, it is not holding the lock, and thread2 can get the lock.

When the wait() method returns, the thread will hold the lock again.

The API documentation of the wait() method in class Object explains this in detail.

染墨丶若流云 2024-10-17 06:18:24

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

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();

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

BTW

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

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

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

The basic problem you have is that you release the synchronized block allowing both threads to go through the loop at the same time. This means either thread can obtain the lock in any order.

AFAIK, The simplest solution is to use a flag.

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();

The most elegant way to have this task done in sync is to have one thread. Threads are specificly designed to execute two tasks with as little dependence as possible between them.

BTW

If notifyAll() is called before wait() is called, the notify will be lost. wait() will wait forever.

You create a Testing object you discard (remove it).

You trap InterruptedException which you print and continue as if nothing happened (i.e. remove the nested catch)

睫毛溺水了 2024-10-17 06:18:24

这是完整的工作代码

public class MyClass

{

MyClass mClass;

公共无效 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();

}
公共静态无效主(字符串[] ar)
{

  new MyClass().doTest();
} 

}

This is the complete working code

public class 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();
} 

}

此生挚爱伱 2024-10-17 06:18:24

公开课我的班级
{
我的班级 mClass;
布尔值 isFirstStartedRunning = true;
公共无效 doTest()
{
最终 int [] a = {1,2,3,4,5,6,7,8,9,10};
最终 char[] c = {'a','b','c','d','e','f','g','h','i','j'};
mClass = 这个;
线程 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();

}
公共静态无效主(字符串[] ar)
{

  new MyClass().doTest();

} 

}
现在检查答案

public class 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;
Thread t1 = new Thread(new 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();

} 

}
check the answer now

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文