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

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

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

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

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

举例说明:

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

  1. package ths;
  2. public class Thread1 implements Runnable {
  3. public void run() {
  4. synchronized (this) {
  5. for (int i = 0; i < 5; i++) {
  6. System.out.println(Thread.currentThread().getName()
  7. + " synchronized loop " + i);
  8. }
  9. }
  10. }
  11. public static void main(String[] args) {
  12. Thread1 t1 = new Thread1();
  13. Thread ta = new Thread(t1, "A");
  14. Thread tb = new Thread(t1, "B");
  15. ta.start();
  16. tb.start();
  17. }
  18. }
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)同步代码块。

  1. package ths;
  2. public class Thread2 {
  3. public void m4t1() {
  4. synchronized (this) {
  5. int i = 5;
  6. while (i-- > 0) {
  7. System.out
  8. .println(Thread.currentThread().getName() + " : " + i);
  9. try {
  10. Thread.sleep(500);
  11. } catch (InterruptedException ie) {
  12. }
  13. }
  14. }
  15. }
  16. public void m4t2() {
  17. int i = 5;
  18. while (i-- > 0) {
  19. System.out.println(Thread.currentThread().getName() + " : " + i);
  20. try {
  21. Thread.sleep(500);
  22. } catch (InterruptedException ie) {
  23. }
  24. }
  25. }
  26. public static void main(String[] args) {
  27. final Thread2 myt2 = new Thread2();
  28. Thread t1 = new Thread(new Runnable() {
  29. public void run() {
  30. myt2.m4t1();
  31. }
  32. }, "t1");
  33. Thread t2 = new Thread(new Runnable() {
  34. public void run() {
  35. myt2.m4t2();
  36. }
  37. }, "t2");
  38. t1.start();
  39. t2.start();
  40. }
  41. }
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

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

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

  1. public void m4t2() {
  2. synchronized (this) {
  3. int i = 5;
  4. while (i-- > 0) {
  5. System.out
  6. .println(Thread.currentThread().getName() + " : " + i);
  7. try {
  8. Thread.sleep(500);
  9. } catch (InterruptedException ie) {
  10. }
  11. }
  12. }
  13. }
	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) {
}
}
} }

结果:
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()方法如下:

  1. public synchronized void m4t2() {
  2. int i = 5;
  3. while (i-- > 0) {
  4. System.out.println(Thread.currentThread().getName() + " : " + i);
  5. try {
  6. Thread.sleep(500);
  7. } catch (InterruptedException ie) {
  8. }
  9. }
  10. }
	public synchronized void m4t2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}

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

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

  1. package ths;
  2. public class Thread3 {
  3. class Inner {
  4. private void m4t1() {
  5. int i = 5;
  6. while (i-- > 0) {
  7. System.out.println(Thread.currentThread().getName()
  8. + " : Inner.m4t1()=" + i);
  9. try {
  10. Thread.sleep(500);
  11. } catch (InterruptedException ie) {
  12. }
  13. }
  14. }
  15. private void m4t2() {
  16. int i = 5;
  17. while (i-- > 0) {
  18. System.out.println(Thread.currentThread().getName()
  19. + " : Inner.m4t2()=" + i);
  20. try {
  21. Thread.sleep(500);
  22. } catch (InterruptedException ie) {
  23. }
  24. }
  25. }
  26. }
  27. private void m4t1(Inner inner) {
  28. synchronized (inner) { // 使用对象锁
  29. inner.m4t1();
  30. }
  31. }
  32. private void m4t2(Inner inner) {
  33. inner.m4t2();
  34. }
  35. public static void main(String[] args) {
  36. final Thread3 myt3 = new Thread3();
  37. final Inner inner = myt3.new Inner();
  38. Thread t1 = new Thread(new Runnable() {
  39. public void run() {
  40. myt3.m4t1(inner);
  41. }
  42. }, "t1");
  43. Thread t2 = new Thread(new Runnable() {
  44. public void run() {
  45. myt3.m4t2(inner);
  46. }
  47. }, "t2");
  48. t1.start();
  49. t2.start();
  50. }
  51. }
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();
}
}

结果:

尽管线程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:

  1. private synchronized void m4t2() {
  2. int i = 5;
  3. while (i-- > 0) {
  4. System.out.println(Thread.currentThread().getName()
  5. + " : Inner.m4t2()=" + i);
  6. try {
  7. Thread.sleep(500);
  8. } catch (InterruptedException ie) {
  9. }
  10. }
  11. }
	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) {
}
}
}

结果:

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

对synchronized(this)的一些理解的更多相关文章

  1. volatile和synchronized与lock的理解

    volatile 特征: a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改. b:禁止特定的处理器重排序. volatile的内存语义: 1.当写一个volatile变量的时候 ...

  2. java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解

    synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...

  3. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  4. 计算机程序的思维逻辑 (66) - 理解synchronized

    上节我们提到了多线程共享内存的两个问题,一个是竞态条件,另一个是内存可见性,我们提到,解决这两个问题的一个方案是使用synchronized关键字,本节就来讨论这个关键字. 用法 synchroniz ...

  5. 深入理解Java并发之synchronized实现原理

    深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...

  6. Java编程的逻辑 (66) - 理解synchronized

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  7. 深入理解并发编程之----synchronized实现原理

    版权声明:本文为博主原创文章,请尊重原创,未经博主允许禁止转载,保留追究权 https://blog.csdn.net/javazejian/article/details/72828483 [版权申 ...

  8. synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

    本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...

  9. 【Java并发编程实战】-----synchronized

    在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...

随机推荐

  1. pscp 命令---windows和linux之间互相拷贝文件的工具

    pscp -r d:\cc root@10.0.0.8:/root/test copy d:\cc content recursively into the /root/test, contains ...

  2. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...

  3. AtCoder Beginner Contest 113 B

    B - Palace Time limit : 2sec / Memory limit : 1024MB Score: 200 points Problem Statement A country d ...

  4. HDU - 2604 矩阵快速幂 字符串递推 两种解法

    记dp[i]为长度i且符合题意的方案数,dp[n]就是解 符合方案的是不含fmf和fff子串的字符串 考虑如何从前面几项递推出后面第i项 (★表示存在生成的非法方案)←其实没啥用处 i=1时 m③ f ...

  5. 1129 Recommendation System (25 分)

    Recommendation system predicts the preference that a user would give to an item. Now you are asked t ...

  6. PHP返回变量或数组的字符串表示:var_export()

    使用var_export()函数可以在服务端程序没有在打印的情况下,配合file_put_contents方便的调试程序,查看变量和数组的内容. 在开发过程中,我们常用var_dump()来打印数组内 ...

  7. openssl-devel和openssl 是什么具体关系

    [转自] https://zhidao.baidu.com/question/919579491101051499.html Redhat在封装openssl的时候,把openssl分成了几个部分,执 ...

  8. Oracle之AUTHID CURRENT_USER

    没有AUTHID CURRENT_USER表示定义者权限(definer rights),以定义者身份执行: 加上AUTHID CURRENT_USER表示调用者权限(invoker rights), ...

  9. poj3262

    一.题意:有n头牛,每头牛每分钟会吃D个菜,把这头牛赶回去需要时间T(人再返回又需要T),一次只能赶回去一头牛,也就是说剩下的牛会继续吃菜.求牛最少吃多少菜 二.思路:贪心.按D/T将牛进行排序,然后 ...

  10. PIE SDK矢量自定义渲染

    1. 功能简介 PIE SDK中关于矢量渲染提供了多种方案,包括简单渲染.分级渲染.唯一值渲染,这几种渲染方式具有一定的通用性,可以满足用户绝大多数的需求. 当面对复杂的业务,当前渲染方案无法满足用户 ...