如何解决有关线程同步的几个问题
|class Q {
int n;
boolean sse = false;
synchronized int get(){
while (!sse)
try{
wait();
}catch(InterruptedException e){
System.out.println(\"Interrupted Exception Caught\");
}
System.out.println(\"Got :\" + n);
sse = false;
notify();
return n;
}
synchronized void put(int n){
while(sse)
try{
wait();
}catch(InterruptedException e){
System.out.println(\"Caught\");
}
this.n = n;
sse = true;
System.out.println(\"Put :\" + n);
notify();
}
}
class Producer implements Runnable{
Q q;
Producer(Q q) {
this.q = q;
new Thread(this,\"Prodcuer\").start();
}
public void run(){
int i = 0;
while(true) {
q.put(i++);
}
}
}
class Consumer implements Runnable{
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this,\"Consumer\").start();
}
public void run(){
while(true) {
q.get();
}
}
}
public class Main {
public static void main(String[] args) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println(\"Press Control C to stop\");
}
}
我有两个问题。
Q1。现在,wait()函数的定义是这样的:告诉调用线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify()为止。
现在在该程序中,两个线程(一个与消费者有关,一个与生产者有关)分别在get和put中使用相同的对象q。那么,对于任何对象,只要有一个线程使用涉及q的函数,就只存在一个对象q的监视器?
Q2在这里,消费者等待直到生产者通知它,但是生产者也等待直到消费者通知它?谁先开始?
在输出中,生产者排在第一位,但是如何?
解决方法
Q只有一台显示器
Producer首先启动,因为您首先在Main中调用了它的构造函数。
, 关于第二个问题:程序启动时,Q对象“为空”,这意味着使用者无法获得任何对象。因此,消费者必须等待,直到生产者放入东西为止。这意味着生产者将首先打印其“放置”,然后消费者可以检索它并打印其“获取”。
另一方面,如果生产者试图在消费者将上一个元素从队列中取出之前再次放一些东西,则生产者必须等待直到被拿走。
这意味着您将交替获得\“ Put \”和\“ Get \”输出(假定输出流不进行某些重新排序)。
这与ѭ1有点不同,此处生产者可以在队列之前为空的情况下继续操作(消费者可以在队列已满的情况下继续操作),而对于SynchronousQueue,它将等待直到消费者准备使用它(这意味着
put
)。和get
在时间上总是重叠的,因此不能在同一线程上调用)。
您的队列更类似于容量为1的ArrayBlockingQueue。
,
jvm中的每个对象(实例)都只有一个监视器。这对于实现预期的行为至关重要(即确保一堆线程中只有一个线程在前进,而其他线程在等待)。
您可以将锁可视化为进入房间所需的一种令牌/通行证。许多医院采用这种方案来确保只有一名服务员可以陪同特定患者。如果您想代替现任服务员,则应wait()
,现任服务员出来并将通行证交给您。只有这样,您才能通过安全性进入限制区域。当然,该方案仅在每个患者只有一次令牌/通行证的情况下有效。否则,安全人员将不可能知道哪个患者已经有服务员。
使用您的代码,生产者线程将首先启动,因为您要在使用者之前创建生产者。但是,如果您想知道首先调用get()
还是put()
中的哪一个,则不能保证顺序。在实践中,通常会先调用ѭ6,因为生产者线程是首先启动的。但是从理论上讲,仍然有可能首先看到ѭ5。这是可能的,因为线程调度程序可能会在生产者线程到达put()调用之前将其关闭。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。