正如我所知,只有一个线程可以在同一块上的同步方法上执行,但在生产者消费者问题中,我可以运行这两种方法。
示例代码
import java.util.concurrent.CountDownLatch;
public class VIV {
public static void main(String[] args) throws Exception {
Number no = new Number();
//Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od,"ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev,"Even");
evenThraed.start();
}
}
class Number {
int no;
boolean flag=false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(!flag) {
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
no=no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=false;
notify();
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(flag) {
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
}
no = no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=true;
notify();
return no;
}
}
class Even implements Runnable {
Number num;
int noOfTime;
Even(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
Number num;
int noOfTime;
Odd(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getOddNo();
}
}
}
OutPut :
因为只创建了一个Number对象并将其传递给在其两个不同的synchronized方法上调用的其他类。这两种方法都是在等待之后打印消息。
答案 0 :(得分:4)
两种方法同时执行的原因是wait()
方法释放锁。一旦synchronized
方法调用wait()
,就会返回锁定,另一个线程可以在同一个对象上调用另一个synchronized
方法。不要以这种方式在wait()
方法中调用synchronized
!
wait()
电话也是您遇到死锁的原因。这就是发生的事情:
odd
方法获取锁定并开始执行。odd
方法打印其第一条消息。odd
方法调用wait()
,释放锁并等待通知。even
方法现在可以获取已释放的锁。even
方法打印其第一条消息。even
方法调用wait()
,释放锁并等待通知。到目前为止,您处于两个synchronized
方法的中间(因为wait()
释放锁定),并且您已经死锁(因为两种方法都在等待)。
除非您确定自己需要的是什么,否则不要致电wait()
。如果您的wait()
只是为了让它等待查看同步是否可以被破坏,您可以尝试使用Thread.sleep()
,这将暂停而不释放任何锁定。通常只需将相关方法或块声明为synchronized
即可,而无需任何wait
/ notify
。
(顺便说一句,拥有一个名为Number
的类并不是一个好主意,因为这是一个标准的JDK类。它是Double
,Integer
的超类,所以上。)
答案 1 :(得分:0)
我不知道你是否想要达到这种目的,如果你想打电话给 EVEN&amp; ODD或者,然后我修改了你的代码。看看下面的代码: -
public class VIV {
public static void main(String[] args) throws Exception {
TestNumber no = new TestNumber();
// Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od, "ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev, "Even");
evenThraed.start();
}
}
class TestNumber {
int no;
boolean flag = false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized
// method
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = false;
notify();
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (!flag) {
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = true;
notify();
// wait block so no other thread can enter on same object synchronized
// method
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (flag) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
}
class Even implements Runnable {
TestNumber num;
int noOfTime;
Even(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
TestNumber num;
int noOfTime;
Odd(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getOddNo();
}
}
}
注意:根据@ chiastic-security 数字的建议已在JDK中定义,我已在此代码中将其重命名为 TestNumber 。
输出
In ODD Method
ODD:1
In Even Method
Even:2
In ODD Method
ODD:3
In Even Method
Even:4
In ODD Method
ODD:5
In Even Method
Even:6
In ODD Method
ODD:7
In Even Method
Even:8
In ODD Method
ODD:9
In Even Method
Even:10
In ODD Method
ODD:11
In Even Method
Even:12
In ODD Method
ODD:13
In Even Method
Even:14
In ODD Method
ODD:15
In Even Method
Even:16
In ODD Method
ODD:17
In Even Method
Even:18
In ODD Method
ODD:19
In Even Method
Even:20