无法通知锁定

无法通知锁定

问题描述:

我已经对java线程编码进行了测试,但是我有一些基本问题。经过几个小时的尝试和搜索,我决定尝试一下!无法通知锁定

我不明白为什么我的等待仍然锁定即使我的通知:

在这里你可以找到我的代码:

public class Mymain { 

    public static void main(String[] args) { 

     for(int i=0;i<100;i++){ 
      new ThreadClass(i).start();  
     } 
    } 
} 

public class ThreadClass extends Thread { 
    static boolean ok = false; 
    int id; 

    public ThreadClass(int i) { 
     id = i; 
    } 

    public void run() { 
     System.out.println("Thread start " + id); 
     Last.toDo(id); 
     if (id == 5) 
      try { 
       waiting(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     if (id != 5) 
      awaking(); 

     System.out.println("thread end " + id); 
    } 

    private synchronized void awaking() { 
     // TODO Auto-generated method stub 
     if (ok) { 
      System.out.println("i'm " + id + " and i'm Awaking 5"); 
      ok = false; 
      notify(); 
      System.out.println("I did the notify and i'm " + id); 
     } 
    } 

    private synchronized void waiting() throws InterruptedException { 
     System.out.println("Sleeping"); 
     ok = true; 
     wait(); 
     System.out.println("Awake 5"); 
    } 
} 

Result

然后开始循环,或者去在死锁不能确定..它应该只是停止与ID = 5的线程,然后下一个线程应重新启动ID = 5 ..但线程5从未醒来后通知...

在结果中,你可以看到我有2个线程试图唤醒线程5和螺纹5的自启动^^

+0

你能告诉我们你的输出是什么,它应该是什么? –

+0

你可以把它放在你的问题中,以便格式化以便于分析吗? –

+0

@WarrenDew完^^ – JustMe

看我做你的代码的一些变化:

  1. 你不能只是notify(),你会通知this。你不能只是wait(),你会永远等下去。你必须在Object上使用这些函数,所以我添加了一个Integer对象(只是为了向你展示 - 你必须选择正确的对象)。
  2. 你哟​​和static synchronized之间的了解。快速搜索会导致你一个完美的答案。
  3. 为什么功能waiting()被同步?只有线程号码5调用它。
  4. 当调用一个Object.notify()/Object.wait(),必须声明在对象同步块。

下面是一些代码:

public class Threads { 
    public static void main(String[] args) { 
     Integer intObject = new Integer(0); 
     for(int i=0;i<100;i++){ 

      new ThreadClass(i, intObject).start();  
     } 
    } 
} 
class ThreadClass extends Thread { 
    static boolean ok = false; 
    int id; 
    Integer intObject; 
    public ThreadClass(int i, Integer intObject) { 
     id = i; 
     this.intObject = intObject; 
    } 

    public void run() { 
     System.out.println("Thread start " + id); 
     //Last.toDo(id); 
     if (id == 5) 
      waiting(); 
     else 
      awaking(this); 

     System.out.println("thread end " + id); 
    } 

    private static synchronized void awaking(ThreadClass t) { 
     if(ok) { 
      System.out.println("i'm " + t.id + " and i'm Awaking 5"); 
      ok = false; 
      synchronized (t.intObject) { 
        t.intObject.notify(); 
       } 
      System.out.println("I did the notify and i'm " + t.id); 
     } 
    } 
    private void waiting(){ 
     System.out.println("Sleeping"); 
     ok = true; 
     synchronized (intObject) { 
      try { 
       intObject.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("Awake 5"); 
    } 
} 
+0

泰的回答很明确^^现在我知道了^^ – JustMe

+1

这将是确定的,不同之处在于使用整数锁定是一个可怕的想法。这不是需要让示例工作。 –

+0

是的,我写了它,只是为了演示如何与一个对象同步工作 – Yinon

的问题是,你不打电话通知()对同一对象总是要等着那你打电话给wait()。特别是,线程5本身正在调用wait(),但例如,线程8正在调用notify()而不是线程5.结果,线程5从未收到通知。

此外,您需要使ok变量volatile确保当一个线程设置它时,其他线程可以看到更改。这不会在这种特殊情况下造成问题,但在其他情况下可能会导致问题。

+0

我走到为此太(第3行),但我不明白我应该怎么办通知线程5.这可能是一些基本的东西我我不理.. ^^ 泰的帮助:d – JustMe

+0

一这样做的方法是用易变的Object变量替换“ok”变量。你会检查nonnull而不是true,并且线程5将创建该对象并等待它。其他线程会通知它是否在那里。 –

+0

是啊,我得到了它TY所有^^ – JustMe

我不明白为什么我的等待仍然锁定即使我的通知:

等待并使用同一个对象实例通知工作。如果你具有例如:

String x1 = "..."; 
String x2 = "..."; 

和线#1的作用:

synchronized (x1) { x1.wait(); } 

和线#2,那么做:

synchronized (x2) { x2.wait(); } 

那么线程#1仍然会等待,因为通知仅限于x2。在您的示例中,由于您使用的是方法同步,因此ID为5的线程正在等待其自己的ThreadClass实例。然后当其他线程调用awaking()时,他们也调用了ThreadClass的实例的通知。如果你想让线程#5看到另一个线程的通知,那么他们应该共享一个锁定对象。

也许是这样的:

final Object lock = new Object(); 
for (int id = 0; id < 100; id++){ 
     new ThreadClass(id, lock).start();  
} 
... 
public class ThreadClass extends Thread { 
    private final Object lock; 
    ... 
    public ThreadClass(int id, Object lock) { 
     this.id = id; 
     this.lock = lock; 
    } 
    ... 
    private void awaking() { 
     ... 
     synchronized (lock) { 
      lock.notify(); 
     } 
     ... 
    } 
    private void waiting() throws InterruptedException { 
     ... 
     synchronized (lock) { 
      lock.wait(); 
     } 
     ... 
    } 
} 
+0

泰的回答很明确^^现在我知道了^^ – JustMe

为什么你不使用notifyAll的()方法?当你调用通知(),这意味着只有一个线程将状态从等待可运行改变,但有可能是情况下,当你这是在排队等候以及多个线程和其他线程,他们将不会收到此通知。在我看来,最好使用notifyAll。

+0

不要这么认为^^我解决了建议从其他成员^^ – JustMe

+0

这篇文章没有准确回答这个问题。如果线程不使用相同的锁,则它们调用的方法无关紧要。 –