如果在线程同步块中将被同步对象修改会发生什么情况?
import java.util.concurrent.TimeUnit;
public class Main
{
public static void main(String[] args) {
Object object = new Object() ;
Syn syn1 = new Syn(object) ;
Syn syn2 = new Syn(object) ;
Thread thread = new Thread(syn1) ;
thread.start() ;
thread = new Thread(syn2) ;
thread.start() ;
}
}
class Syn implements Runnable
{
private Object object ;
public Syn(Object object) {
this.object = object;
}
@Override
public void run() {
synchronized (object)
{
object = new Object() ;
try {
System.out.println("in sleep " + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
System.out.println("out sleep" + Thread.currentThread().getName());
}
catch (Exception e)
{
System.err.println(e);
}
}
}
}
我用上面的程序测试发现在同步块中修改了object并不会影响两条线程的互斥, 那么为什么推荐使用不可变对象或者专用的锁来实现线程的互斥呢?
Faites ceci :
Les résultats obtenus peuvent être incompatibles avec ce que vous attendiez. Ce que la synchronisation verrouille est en fait le contenu pointé par la référence de l'objet. Lorsque vous reliez la référence
object à un nouvel Object(), le contenu verrouillé ne changera pas. C'est-à-dire que le contenu pointé par l'objet dans la surface
de syn2 est toujours verrouillé, et il doit attendre la fin du bloc de synchronisation dans syn1 avant de pouvoir continuer à s'exécuter, donc ils (syn1, syn2)
sont exécutés séquentiellement. Cela rend difficile la lecture et la maintenance du code.
Java vous recommande donc d'utiliser final pour modifier l'objet qui nécessite une synchronisation afin de garantir qu'il ne sera pas lié à d'autres objets.
Votre object=new Object(); ici est inutile. La référence d'objet de l'objet actuel que vous avez modifié ici peut en effet refléter l'exclusion mutuelle la première fois que le thread l'exécute, mais elle ne la reflétera pas la deuxième fois. exécuté.
Vous pouvez les écrire vous-même :
Vous avez déclaré un objet dans Syn, ce qui fait que l'objet détenu par chaque instance Syn n'est pas le même, vous pensez donc qu'il y a un problème. La solution que j'ai utilisée est la suivante :