java中使用对象锁进行同步
我有两个线程 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?:falseIs Thread1 holding lock of
Testing.class?:true1
Thread1:Going to wait
Is Thread2 holding lock of
Testing.class?:falseIs Thread2 holding lock of
Testing.class?:trueThread2: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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
详细了解 Java 并发。
调用
wait
释放锁。Read a bit more about Java Concurrency.
Calling
wait
releases the lock.当您调用
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 thewait()
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 classObject
explains this in detail.您遇到的基本问题是释放同步块,从而允许两个线程同时通过循环。这意味着任一线程都可以按任意顺序获取锁。
AFAIK,最简单的解决方案是使用标志。
同步完成此任务的最优雅的方法是使用一个线程。线程专门设计用于执行两个任务,并且它们之间的依赖性尽可能小。
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.
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)
这是完整的工作代码
public class MyClass
{
MyClass mClass;
公共无效 doTest()
{
}
公共静态无效主(字符串[] ar)
{
}
This is the complete working code
public class MyClass
{
MyClass mClass;
public void doTest()
{
}
public static void main(String [] ar)
{
}
公开课我的班级
{
我的班级 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(){
}
公共静态无效主(字符串[] ar)
{
}
现在检查答案
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 static void main(String [] ar)
{
}
check the answer now