我目前正在学习关键部分&信号量,我被这部分困住了。我希望你们能给我一个洞察力。
我有这三种类型的线程:一种是在堆栈上执行pop(),另一种在同一堆栈上执行push(),最后一种是打印该堆栈的值。目前,我已将wait()和signal()置于我认为是关键部分的位置。
class Example{
public static void main(){
//create thread objects
StackPop p1 = new StackPop();
StackPop p2 = new StackPop();
StackPop p3 = new StackPop();
StackPush ps1 = new StackPush();
StackPush ps2 = new StackPush();
StackPush ps3 = new StackPush();
StackValues s1 = new StackValues();
StackValues s2 = new StackValues();
StackValues s3 = new StackValues();
//then we start these threads in mix orders
p1.start();
s3.start();
ps2.start();
// etc
}
}
class StackPop extends Thread{
public void run(){
mutex.wait();
pop();
SOP("value popped is " + get.popVal);
mutex.signal();
}
}
class StackPush extends Thread{
public void run(){
mutex.wait();
push();
SOP("value inserted is " + get.pushVal);
mutex.signal();
}
}
class StackValues extends Thread{
public void run(){
mutex.wait();
for(int i = 0; i<stack.size(); i++)
S.O.P.("["+getVal(i)+"]"); //where getVal() will retrieve value at that index
mutex.signal();
}
}
上面的代码是简化版,但想法是一样的。我的问题是即使我使用wait()和signal(),我仍然得到一个非常奇怪的输出。例如,我的输出的一部分将显示“[1] [2] [3]插入的值是3 [5] [@] [@]”(其中@表示内部没有数字)。我意识到这是因为当for循环获取值时,处理器让另一个线程运行。我假设wait()和signal()会自动使其成为原子,但也许我错过了一些东西。
答案 0 :(得分:0)
您可以在关键部分使用锁定或“同步”。您可以在http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html中查看更多内容 你可以使用相同的想法pop()push()等..
使用互斥锁;
try {
mutex.acquire();
try
{
// work
} finally {
mutex.release();
}
} catch(InterruptedException ie) {// ...}
来源 - &gt; http://java.dzone.com/articles/dnp-java-concurrency- - 部分-4
“我有这三种类型的线程:一个会在堆栈上执行pop(),另一个在同一个堆栈上执行push(),最后一个会打印该堆栈的值”
您正在为每个线程使用3个不同的堆栈,这就是您遇到意外情况的原因。你在一个堆栈上弹出,从不同的堆栈推送,最后从另一个堆栈打印。
您应该执行以下操作:
public class Teste {
Thread t1;
Thread t2;
Thread t3;
Stack<Integer> stack = new Stack <Integer>();
private final Semaphore mutex = new Semaphore(1);
public Teste ()
{
Runnable r1 = new Runnable()
{
public void run()
{
pop();
} // run()
}; // runnable
Runnable r2 = new Runnable()
{
public void run()
{
for(int x = 0; x < 3; x++)
push(x);
} // run()
}; // runnable
Runnable r3 = new Runnable()
{
public void run()
{
for(int x = 0; x < 3; x++)
print();
} // run()
}; // runnable
this.t1 = new Thread(r1); // Create the thread associating the runnable
this.t2 = new Thread(r2);
this.t3 = new Thread(r3);
}
public void pop()
{
try {
mutex.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
stack.pop();
mutex.release();
}
// Similar to pop
public void push(int x){ //..}
public void print(){
try {
mutex.acquire();
} catch (InterruptedException e) {e.printStackTrace();}
for(int i = 0; i<stack.size(); i++)
System.out.println("["+stack.get(i)+"]");
mutex.release();
}
}
public static void main(String argv[])
{
Teste t = new Teste();
t.t2.start();
t.t1.start();
t.t3.start();
}
答案 1 :(得分:0)
要小心,wait是从Object继承的,它的反面是通知 - 你可能会调用错误的方法。
此外,Java有一个本机同步机制,synchronized关键字,您可能想要调查它。