对synchronized(this)的一些理解

2016-02-19 17:04 2 1 收藏

有一种朋友不在生活里,却在生命力;有一种陪伴不在身边,却在心间。图老师即在大家的生活中又在身边。这么贴心的服务你感受到了吗?话不多说下面就和大家分享对synchronized(this)的一些理解吧。

【 tulaoshi.com - 编程语言 】

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

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

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

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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

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

  举例说明:

  一、当两个并发线程访问同一个对象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();
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  

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();
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  

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

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

  

//修改Thread2.m4t2()方法:
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  

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

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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  //修改Thread2.m4t2()方法如下:

  

public synchronized void m4t2() {
int i = 5;
while( i-- 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  

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

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

  

package ths;
public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象锁
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt3.m4t1(inner);
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt3.m4t2(inner);
}
}, "t2"
);
t1.start();
t2.start();
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。

  

t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0

  现在在Inner.m4t2()前面加上synchronized:

  

private synchronized void m4t2() {
int i = 5;
while(i-- 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}

  结果:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。

  

t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0

来源:http://www.tulaoshi.com/n/20160219/1614080.html

延伸阅读
一:我该如何创建自己的MIB? 首先:要定义自己的MIB,要先熟悉ASN.1的语法,其中有个老外的一本MIB书很好,MIB的RFC文档就是它定义的好像。 其次:多看其他的MIB,其实定义比较简单,就是TYPE,标量,表三个主要的东西。 二:我实现一个代理进程,如果捕获SNMP的端口信息那同一机器上另外的代理进程不就没办法捕获管...
标签: 拼布
初入门的拼布朋友,遇到压线的时候,总会想着表布图案与压线图案怎么配合才好看呢,这里我将引用在拼布教室上看来学来的知识和大家分享一下。 对角连线: 通常最受欢迎也最常见的压线图案是一个布片里,角对角连线。只需要通过目测,直接用尺画线就可以,非常的方便好用。 说到这我添上几句,如果...
标签: 皮肤护理
问答 图钉提问: 我最近发现自己患上了梅毒,脸上长满了豆豆,吃了不少药物都没啥好的效果,有时候下体还会出现瘙痒和异味,吃的时候还会出现其他的症状,医生说我需要去做个治疗。 想得到帮助:梅毒要吃些水果吗? 图老师解答: 你好,这种情况不一定会被感染,但风险性很高,建议去医院做一个血清检查。因为不能保证生殖器没有轻微的皮损...
Java开发学习过程中应该理解的一些重点内容 数值类型: 虽然是面向对象的语言,但是在使用上数值类型还是必不可少的,假如在C的学习中已经把握了C的数值计算和转换规则,那我想这里应该没有什么问题,只有两点需要注重:1、14.0这样的浮点常量被认为是double型,只有加上f后缀才是float型的;2、整数常量说起来被认为是int型,但是...
标签: Web开发
用jQuery的时候,刚开始一直以为用$("#someid")取出来的是dom对象的扩展,于是就很自在的用$("#someid").value,$("#someid").text之类的,可惜一直取不出要的值。后来才发现,它并不是扩展。如果要取类似上面的值,就要用$("#someid").val(),$("#someid").text()。这些还是在查看了它的api文档以后才发现的,不禁要感慨一声,JavaScripty...

经验教程

697

收藏

64
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部