黑马程序员技术交流社区

标题: synchronized [打印本页]

作者: 曾辉    时间: 2012-2-11 14:25
标题: synchronized
在线程同步的时候为什么要使用对象监视器,什么是对象监视器?

有同步块和同步方法,同步块前加synchronized(对象){  },为什么要有括号中的对象?这个对象的作用是什么?如果没有对象这个对象监视器会怎么样?

这个对象应该是哪个对象,可能我说的不够准确,或者应该说这个对象的监视器应该是哪个对象的监视器,是随便的吗,还是有什么要求?也不能太随便吧。

例如在一个方法里,有synchronized块,这个对象监视器应该是?
作者: Akm    时间: 2012-2-11 14:33
1 这个对象就相当于一扇门,里面锁着的是共享的资源,每次只能有一个人能进入,并且只能容纳一个人,也就是说只有一个线程能获得这个锁。
2 没有这扇门的话,大家就能一拥而入,对资源进行访问,导致资源的状态混乱,从而出现不正确的结果
3 一般来说,这个对象就是大家要争夺的资源,也就是说,当我使用这个资源的时候,其他人不得执行,但也可以是一个不相干的资源,纯粹是起到锁的作用(高级应用
作者: 孙海亮    时间: 2012-2-11 14:50
本帖最后由 孙海亮 于 2012-2-11 15:10 编辑

  监视器就就相当于现实中的锁啊,当多个线程操作同一堆数据时,必须的保证数据的唯一性啊。毕老师讲过一个经典的例子就是火车上的卫生间。一节车厢那么多人要去厕所,当其中一个进去时,就得把锁锁起来(这里的锁就相当于监视器),当别的人要进来就得看门呗锁起来没,锁起来他就进不去。等其中那个人出来锁打开,下一个才可以进去。进去后继续的锁起来啊。这和线程一样的,不锁线程就不安全。
  synchronized()这括号中锁的是唯一性的对象啊,。synchronized()里不放对象没那么就相当于商店里卖的那个还没放在做用的东西上所以这个所就相当于一把没用的锁。


    一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

     四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.

作者: 尹旗龙    时间: 2012-2-11 15:24
每个Object只有一把锁(Lock)与之关联,当进行到Synchronized语句或函数的时候,这把锁就会被当前的线程(thread)拿走,其他的(thread)再去访问的时候拿不到锁就被暂停了,synchronized(对象){  }中的对象可以是一个任何Object对象或数组,并不一定是它本身对象或者类,谁拥有这个锁,谁就能够操作该块程序代码,这样用当然是为了线程的同步了,否则多线程就不安全了
作者: 戴振良    时间: 2012-2-11 21:04
建议一定要看看张孝详老师的基础视频教程中的《多线程》的视频,那里面有解释,而且有很生动的比喻说明,还有细致的实例代码,去看一遍保证你明白,当然不明白的话可以看第二遍,我就 是看到第三遍的时候完全明白了。
作者: 任奇    时间: 2012-2-11 21:10
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

举例说明:  
     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

package ths;

public class Thread1 implements Runnable {  
     public void run() {  
          synchronized(this) {  
               for (int i = 0; i < 5; i++) {  
                    System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);  
               }  
          }  
     }  
     public static void main(String[] args) {  
          Thread1 t1 = new Thread1();  
          Thread ta = new Thread(t1, "A");  
          Thread tb = new Thread(t1, "B");  
          ta.start();  
          tb.start();  
     }
}

结果:  
     A synchronized loop 0  
     A synchronized loop 1  
     A synchronized loop 2  
     A synchronized loop 3  
     A synchronized loop 4  
     B synchronized loop 0  
     B synchronized loop 1  
     B synchronized loop 2  
     B synchronized loop 3  
     B synchronized loop 4

作者: 张青峰    时间: 2012-2-11 22:15
举例说明:



一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。



package ths;

public class Thread1 implements Runnable {
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}



结果:



A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4



二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。



package ths;

public class Thread2 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt2.m4t1();
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt2.m4t2();
}
}, "t2"
);
t1.start();
t2.start();
}
}



结果:



t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2