我是多线程编程的新手。在我的代码中,线程试图获取几行的锁。对于少数上下文切换,这些行工作得非常好,但随后停止(可能是死锁)。
另一方面,如果使用synchronized
块,那么一切正常。
我有四节课。
1。 PetersonAlgorithm.java
package com.ashish.master;
public class PetersonAlgorithm {
boolean wantCS[] = {false, false};
int turn = 1;
public void requestCS(int i) {
System.out.println("Lock requested by the thread - " + i);
wantCS[i] = true;
turn = 1 - i;
while(wantCS[1-i] && turn == 1-i);
}
public void releaseCS (int i) {
wantCS[i] = false;
turn = i - 1;
System.out.println("Lock released by the thread - " + i);
}
}
如果有人认为上述算法不正确,请告诉我,并随时提出建议。
2。 Runner.java
package com.ashish.master;
public class Runner {
public static Incrementer runnableInstance = new Incrementer();
public static Thread inc1 = new Thread(runnableInstance, "0");
public static Thread inc2 = new Thread(runnableInstance, "1");
public static void main(String args[]) {
inc1.start();
inc2.start();
try{
inc1.join();
inc2.join();
} catch (InterruptedException ex) {
System.out.println("The threads have been interrupted while waiting for the join ---> " + ex.getMessage());
}
System.out.println("The total turns taken by incrementer are ----> " + runnableInstance.turns);
}
}
第3。 Incrementer.java - 如果使用synchronized
块而不是Peterson算法,一切正常。
package com.ashish.master;
public class Incrementer implements Runnable {
public long turns = 0;
public PetersonAlgorithm pa = new PetersonAlgorithm();
@Override
public void run() {
System.out.println("Thread " + this.toString() + "started.....");
while(true) {
pa.requestCS(Integer.parseInt(this.toString()));
// synchronized(this) {
if(DataStore.data < 1000000) printCriticalSection();
else break;
// }
pa.releaseCS(Integer.parseInt(this.toString()));
}
}
public void printCriticalSection() {
System.out.println("The value of the number is increased by thread " +
this.toString() +" to --> " + DataStore.increase());
turns ++;
}
@Override
public String toString() {
return Thread.currentThread().getName();
}
}
4。 DataStore.java 用于模拟数据源的类 - 只需增加数量
package com.ashish.master;
public class DataStore {
public static long data = 0L;
public static long increase() {
DataStore.data += 1;
return DataStore.data;
}
}
答案 0 :(得分:1)
你的runnables从不观察彼此的监视器(wantCS和转弯),因为它们有不同的实例......每个runnable都需要使用同一组共享的监视器!
使用蓝色药丸并使用同步块访问使您的PetersonAlgorithm变量静态不变...
或者拿红色药丸为你的旗帜监视器(wantCS)和指示器监视器(转向)创建一个Class。然后用一个“自己的旗帜”,一个“观察旗”和一个“指示符”来定义你的runnable。两个Runnable都将具有相同的指示符实例(因此需要同步),而标志实例将被越过(R1的自己的标志将是R2的观察标志,R2的自己的标志是R1的观察标志)。您也应该同步标记方法,因为您不希望在观察时升高或降低标记。
然后几步:
答案 1 :(得分:0)
每个可运行的实例都有自己的PetersonAlgorithm实例。因此,两个runnables对彼此一无所知,并且总是能够立即访问临界区。尝试使用static
方法将PetersonAlgorithm类实现为static
类。然后改变行
pa.requestCS(Integer.parseInt(this.toString()));
// ...
pa.releaseCS(Integer.parseInt(this.toString()));
进入
PetersonAlgorithm.requestCS(Integer.parseInt(this.toString()));
// ...
PetersonAlgorithm.releaseCS(Integer.parseInt(this.toString()));