这可以"同步"工作吗?

Joh*_*ohn 2 java multithreading


1.这里使用同步的方式是否正确?
2.当一个线程访问randomScore时,是否锁定了randomScore,以便其他线程无法访问randomScore?
3.如果只有changeRandomScore()可以访问randomScore变量,并且只有一个线程可以访问changeRandomScore(),那么一次只有一个线程可以访问randomScore.这是对的吗?

    import java.*;


public class StudentThread extends Thread {
    int ID;  
    public static int randomScore;

      StudentThread(int i) {
          ID = i;
      }

      public void run() {
          changeRandomScore();

          System.out.println("in run");
      }
public synchronized void changeRandomScore() {
    randomScore = (int) (Math.random()*1000);
}
public static void main(String args[]) throws Exception {
    for (int i = 1;i< 10 ;i++) 
    {
            StudentThread student = new StudentThread(5);

            student.start(); 
            Thread.sleep(100);
            System.out.println(randomScore);
    }             
}  
}
Run Code Online (Sandbox Code Playgroud)

Paŭ*_*ann 6

您在这里访问不同对象的synchronized-methods中的静态变量.这里的同步没有实际效果,因为每个线程都使用自己的监视器(在这种情况下是线程对象).对于共享变量,您也应该使用共享监视器.

这是一个正确同步的变体:

public class StudentThread extends Thread {
  int ID;  
  private static int randomScore;
  private static final Object scoreLock = new Object();

  StudentThread(int i) {
     ID = i;
  }

  public void run() {
     changeRandomScore();

     System.out.println("in run");
  }
  public void changeRandomScore() {
     int tmp = (int) (Math.random()*1000);
     // no need to synchronize the random()-call, too.
     synchronized(scoreLock) {
        randomScore = tmp;
     }
  }
  public static void main(String args[]) throws Exception {
      for (int i = 1;i< 10 ;i++) 
      {
          StudentThread student = new StudentThread(5);

          student.start(); 
          Thread.sleep(100);
          synchronized(scoreLock) {
              System.out.println(randomScore);
          }
      }             
  }  
}
Run Code Online (Sandbox Code Playgroud)

不同之处在于我们现在使用公共锁定对象(scoreLock)并将其用作synchronized块的参数,并且我们还在读取分数时在main方法中同步此对象.

或者,我们也可以声明方法public static synchronized void changeRandomScore()(这意味着它使用类对象作为监视器)并在main方法中同步StudentThread.class.

是的,正如其他人所说:如果你想确保只有正确同步才能访问变量,不要做到public.