Java 代码块上的同步

Java 代码块上的同步,java,synchronization,Java,Synchronization,我理解代码块的同步意味着每次只有一个线程可以访问特定的代码,即使很多线程都在等待访问该代码 当我们在run方法中编写线程类时,我们通过给定对象来启动同步块。 比如说 class MyThread extends Thread{ String sa; public MyThread(String s){ sa=s; } public void run(){ synchronized(sa){ if(sa.equals("notd

我理解代码块的同步意味着每次只有一个线程可以访问特定的代码,即使很多线程都在等待访问该代码

当我们在run方法中编写线程类时,我们通过给定对象来启动同步块。 比如说

 class MyThread extends Thread{
   String sa;
   public MyThread(String s){
       sa=s;
   } 
   public void run(){
     synchronized(sa){
         if(sa.equals("notdone"){
             //do some thing on object
         }
     }
   }    
 }

在这里,我们给sa对象提供了同步块的需要。我们将如何为该特定代码块提供同步,所有在此对象上同步的线程将等待当前线程完成其工作。例如,如果您对希望同步的集合进行了读/写操作,这将非常有用。因此,您可以在方法
set
get
中编写同步化块。在这种情况下,如果一个线程正在读取信息,那么不是所有其他想要读取或写入的线程都将等待。

我建议

  • 扩展可运行而不是线程
  • 不要在外部服务器上锁定Runnable。相反,您应该调用一个可能使用内部锁的方法
  • 字符串作为锁不是一个好的选择。这意味着“hi”和“hi”将共享一个锁,但新字符串(“hi”)将不共享
  • 如果要在线程的生命周期内锁定所有其他线程,为什么要使用多个线程

同步块的参数对象是块锁定的对象。 因此,具有相同对象的所有同步块相互排除(以及该相同对象的所有同步方法)同时执行

如果你有这个例子

class ExampleA extends Thread() {

    public ExampleA(Object l) {
       this.x = l;
    }

    private Object x;

    public void run() {
        synchronized(x) {     // <-- synchronized-block A
            // do something
        }
    }
}
class ExampleB extends Thread() {

    public ExampleB(Object l) {
       this.x = l;
    }

    private Object x;

    public void run() {
        synchronized(x) {     // <-- synchronized-block B
            // do something else
        }
    }
}

Object o1 = new Object();
Object o2 = new Object();

Thread eA1 = new ExampleA(o1);
Thread eA2 = new ExampleA(o2);
Thread eB1 = new ExampleB(o1);
Thread eB2 = new ExampleB(o2);

eA1.start(); eA2.start(); eB1.start(); eB2.start();
这看起来像是您试图避免在比较和工作时有人将您的实例变量
sa
更改为另一个字符串,但这并不能避免这种情况

同步在变量上不起作用,它在对象上起作用-所讨论的对象通常应该是包含变量的某个对象(在您的情况下是当前的
MyThread
对象,可通过
this
访问),或者是仅用于同步的特殊对象,这是不变的


正如Peter Lawrey所说,字符串对象通常是同步锁的错误选择,因为所有相等的字符串文字都是同一个对象(即,将排除彼此的同步块),而相等的非文字字符串(例如,在运行时创建的)不是同一个对象,因此不会排除其他此类对象或文字的同步块,这通常会导致微妙的错误。

所以问题是块同步的对象的功能是什么

对象的所有实例都有所谓的监视器。在正常执行中,此监视器是无主的

希望进入同步块的线程必须占用对象监视器。但是,一次只能有一个线程拥有监视器。因此,如果监视器当前无主,线程将占有并执行同步的代码块。线程在离开同步块时释放监视器


如果监视器当前拥有,那么需要进入同步块的线程必须等待监视器被释放,这样它才能获得所有权并进入块。可以有多个线程在等待,如果是这样,那么只有一个线程被赋予监视器的所有权。其余的将返回等待。

请澄清您的问题好吗?同步块的要点是多线程环境中对易失性字段的线程安全访问。本教程可能会有所帮助:@reef sir为什么以前存在的一些答案现在被删除了…先生..我知道同步块将做什么,但我不知道为特定的同步块指定对象需要什么..好的,我明白你的意思,可能是我的代码不适合锁定字符串对象。我在问这个问题在正常的同步方法中,我们不提供任何对象。但在同步块中,我们提供一个对象,这有什么需要?在复杂对象中,可以有许多锁,并且每个锁都需要一个同步块。有时您不想锁定此,因为它也可以在类之外锁定,所以您可能会锁定您提供的对象。一些线程安全的集合没有线程安全的迭代器,因此您必须锁定集合,仅用于迭代(但不包括其他)
 synchronized(sa){
     if(sa.equals("notdone"){
         //do some thing on object
     }
 }