对synchronized(this)的一些理解

2016-02-19 17:04 0 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对象所有同步代码部分的访问都被暂时阻塞。

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

  举例说明:

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

  结果:

(本文来源于图老师网站,更多请访问https://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();
}
}

  结果:

(本文来源于图老师网站,更多请访问https://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) {
}
}
}
}

  结果:

(本文来源于图老师网站,更多请访问https://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对象所有同步代码部分的访问都被暂时阻塞。

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

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

  

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

  结果:

(本文来源于图老师网站,更多请访问https://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();
}
}

  结果:

(本文来源于图老师网站,更多请访问https://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) {
}
}
}

  结果:

(本文来源于图老师网站,更多请访问https://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

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

延伸阅读
Java开发学习过程中应该理解的一些重点内容 数值类型: 虽然是面向对象的语言,但是在使用上数值类型还是必不可少的,假如在C的学习中已经把握了C的数值计算和转换规则,那我想这里应该没有什么问题,只有两点需要注重:1、14.0这样的浮点常量被认为是double型,只有加上f后缀才是float型的;2、整数常量说起来被认为是int型,但是...
标签: 酥油
抹茶奶黄酥的做法 抹茶奶黄酥做法和步骤1黄油室温软化,加入糖搅打均匀。分次加入蛋液搅打均匀。所有粉类混合筛入拌匀。加入牛奶混合均匀。放蒸锅蒸25分钟左右,中途取出用筷子搅拌2-3次。制作好的奶黄馅稍晾凉用手抓捏成团,冷藏备用。使用前分成分成12等分的小圆,盖上保鲜膜备用。 2小贴士:1、因为液体量比较多,会出现水油分离的现象...
抹茶酸奶冻芝士的做法 抹茶酸奶冻芝士做法和步骤1原味芝士液:奶油奶酪,白砂糖,酸奶混合,隔热水软化。吉利丁片凉水泡软,沥干加入牛奶中,隔热水融化,倒入芝士液中拌匀,用手持搅拌器打匀至无颗粒状态,若气泡很多可过筛一遍。加入打至6-7分发的淡奶油拌匀即成。2倒入模子中,入冰箱冷冻。3抹茶芝士液:奶油奶酪,白砂糖,酸奶混合,隔热水...
标签: 团子 小吃
清明团子的做法 清明团子做法和步骤1称量面团部分的材料,艾草摘去老叶清理后的,称量200g,洗净沥干。锅中水煮开,水中加一点点小苏打(也可不加),把艾草放入焯水。2焯好水的艾草立刻捞出,用冷水冲凉后挤干水份。焯过水的艾草加200ml热水,放入搅拌机中搅打成细腻的艾草糊。 3把糯米粉、大米粉、白糖放入大盆中混合,倒入艾草糊,搅拌一...
标签: 椒盐
椒盐馒头片的做法 椒盐馒头片做法和步骤1馒头切片。鸡蛋打入平盘中,加少许盐搅散。放入一半的馒头片,两面都沾满蛋液,备用。2平底锅里热油,放入未沾蛋液的一半馒头片,迅速翻面使得两面都有浸油,中火煎至两面金黄即可。吃时可沾椒盐。 3通常一次蒸很多馒头,剩余的馒头或冷藏,或冷冻。下次再吃时,直接加热当然是最普通的办法。除此,...

经验教程

936

收藏

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