java中Synchronized关键字之对象锁

    当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题。

  多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。而用的最多的就是synchronized关键字。

  语法:Synchronized(对象锁){}

  被synchronized关键字修饰的一个方法,则这个方法叫做同步方法

  静态synchronized方法的锁是对应的字节码对象(Class对象),而非静态synchronized方法的锁是个实例对象

  当synchronized方法执行完或发生异常时,会自动释放锁。


1.是否使用synchronized关键字的不同


  1. package threadDemo;
  2.  
  3. public class ThreadDemo
  4. {
  5. public static void main(String[] args)
  6. {
  7. Example example = new Example();
  8.  
  9. Thread t1 = new TH(example);
  10. Thread t2 = new TH(example);
  11.  
  12. t1.start();
  13. t2.start();
  14. }
  15.  
  16. }
  17.  
  18. class Example
  19. {
  20. public synchronized void show()
  21. {
  22. for (int i = 0; i < 10; ++i)
  23. {
  24. try
  25. {
  26. Thread.sleep(500);
  27. }
  28. catch (InterruptedException e)
  29. {
  30. e.printStackTrace();
  31. }
  32. System.out.println(i);
  33. }
  34. }
  35.  
  36. }
  37.  
  38. class TH extends Thread
  39. {
  40. private Example example;
  41.  
  42. public TH(Example example)
  43. {
  44. this.example = example;
  45. }
  46.  
  47. @Override
  48. public void run()
  49. {
  50. example.show();
  51. }
  52.  
  53. }

运行结果:

  1. show()0
  2. show()1
  3. show()2
  4. show()3
  5. show()4
  6. show()5
  7. show()6
  8. show()7
  9. show()8
  10. show()9
  11. show2()0
  12. show2()1
  13. show2()2
  14. show2()3
  15. show2()4
  16. show2()5
  17. show2()6
  18. show2()7
  19. show2()8
  20. show2()9

是否在show()方法前加上synchronized关键字,这个例子程序的执行结果会有很大的不同。

  如果不加synchronized关键字,则两个线程同时执行show()方法,输出是两组并发的。

  如果加上synchronized关键字,则会先输出一组0到9,然后再输出下一组,说明两个线程是顺次执行的。


2.同步方法的锁是this


在静态同步方法中的对象锁是这个类的字节码文件对象。类.class

要想获取一个类的字节码文件对象,有两种方法

1通过当前类.class

2通过当前类的实例对象.getClass()方法获取

  1. public class ClassDemo {
  2. void show(){
  3. //任何一个类可以通过.class来获取字节码文件对象
  4. Class<ClassDemo> c = ClassDemo.class;
  5. //任何一个对象可以通过getClass()方法来获取字节码文件对象
  6. Class<? extends ClassDemo> class1 = new ClassDemo().getClass();
  7.  
  8. }
  9. }

验证同步方法的对象锁是this

  思路:

  启动两个线程,让一个线程进入同步代码块,一个线程进入同步方法

  用到了一个中间的控制变量boolean flag

  线程对象的run中,实现三个窗口出售100张票的功能,让程序进入一个同步代码块中,并且在线程对象中,再定义一个同步方法,功能与同步代码块中的功能相同。

package threadDemo;

public class ThreadDemo03 {

public static void main(String[] args) {
T t = new T();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);

t1.start();
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
t.flag=false;
t2.start();
}

}

class T implements Runnable {
private int ticket = 100;
boolean flag = true;
Object obj = new Object();

@Override
public void run() {
if (flag) {
while (true) {
//synchronized (this) {
synchronized (obj){
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}

}
}else{
while(true){
show();
}
}

}

public synchronized void show(){//synchronized (this)
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}

}

运行结果:

  1. Thread-0正在出售第100张票
  2. Thread-1正在出售第99张票
  3. Thread-0正在出售第98张票
  4. Thread-1正在出售第97张票
  5. Thread-0正在出售第96张票
  6. Thread-1正在出售第95张票
  7. Thread-0正在出售第94张票
  8. Thread-1正在出售第93张票
  9. Thread-0正在出售第92张票
  10. Thread-1正在出售第91张票
  11. Thread-0正在出售第90张票
  12. Thread-1正在出售第89张票
  13. Thread-0正在出售第88张票
  14. Thread-1正在出售第87张票
  15. Thread-0正在出售第86张票
  16. Thread-1正在出售第85张票
  17. Thread-0正在出售第84张票
  18. Thread-1正在出售第83张票
  19. Thread-0正在出售第82张票
  20. Thread-1正在出售第81张票
  21. Thread-0正在出售第80张票
  22. Thread-1正在出售第79张票
  23. Thread-0正在出售第78张票
  24. Thread-1正在出售第77张票
  25. Thread-0正在出售第76张票
  26. Thread-1正在出售第75张票
  27. Thread-0正在出售第74张票
  28. Thread-1正在出售第73张票
  29. Thread-0正在出售第72张票
  30. Thread-1正在出售第71张票
  31. Thread-0正在出售第71张票
  32. Thread-1正在出售第70张票
  33. Thread-0正在出售第69张票
  34. Thread-1正在出售第68张票
  35. Thread-0正在出售第68张票
  36. Thread-1正在出售第66张票
  37. Thread-0正在出售第67张票
  38. Thread-1正在出售第65张票
  39. Thread-0正在出售第65张票
  40. Thread-0正在出售第64张票
  41. Thread-1正在出售第63张票
  42. Thread-0正在出售第62张票
  43. Thread-1正在出售第61张票
  44. Thread-1正在出售第60张票
  45. Thread-0正在出售第59张票
  46. Thread-0正在出售第58张票
  47. Thread-1正在出售第57张票
  48. Thread-1正在出售第56张票
  49. Thread-0正在出售第55张票
  50. Thread-1正在出售第54张票
  51. Thread-0正在出售第54张票
  52. Thread-1正在出售第53张票
  53. Thread-0正在出售第52张票
  54. Thread-1正在出售第51张票
  55. Thread-0正在出售第50张票
  56. Thread-0正在出售第49张票
  57. Thread-1正在出售第48张票
  58. Thread-0正在出售第47张票
  59. Thread-1正在出售第47张票
  60. Thread-1正在出售第46张票
  61. Thread-0正在出售第45张票
  62. Thread-1正在出售第44张票
  63. Thread-0正在出售第43张票
  64. Thread-0正在出售第42张票
  65. Thread-1正在出售第41张票
  66. Thread-0正在出售第40张票
  67. Thread-1正在出售第39张票
  68. Thread-0正在出售第38张票
  69. Thread-1正在出售第37张票
  70. Thread-0正在出售第36张票
  71. Thread-1正在出售第35张票
  72. Thread-0正在出售第34张票
  73. Thread-1正在出售第33张票
  74. Thread-0正在出售第32张票
  75. Thread-1正在出售第31张票
  76. Thread-0正在出售第30张票
  77. Thread-1正在出售第29张票
  78. Thread-0正在出售第28张票
  79. Thread-1正在出售第27张票
  80. Thread-0正在出售第26张票
  81. Thread-1正在出售第25张票
  82. Thread-0正在出售第24张票
  83. Thread-1正在出售第23张票
  84. Thread-0正在出售第22张票
  85. Thread-1正在出售第21张票
  86. Thread-0正在出售第20张票
  87. Thread-1正在出售第19张票
  88. Thread-0正在出售第18张票
  89. Thread-1正在出售第17张票
  90. Thread-0正在出售第16张票
  91. Thread-1正在出售第15张票
  92. Thread-0正在出售第14张票
  93. Thread-1正在出售第13张票
  94. Thread-0正在出售第12张票
  95. Thread-1正在出售第11张票
  96. Thread-0正在出售第10张票
  97. Thread-1正在出售第9张票
  98. Thread-0正在出售第8张票
  99. Thread-1正在出售第7张票
  100. Thread-0正在出售第6张票
  101. Thread-1正在出售第5张票
  102. Thread-0正在出售第4张票
  103. Thread-1正在出售第3张票
  104. Thread-0正在出售第2张票
  105. Thread-1正在出售第1张票
  106. Thread-0正在出售第0张票

通过改变class T中同步代码块synchronized (对象锁) 的对象锁obj改成this依然成立。所以同步方法的对象锁是this。

其中public synchronized void show()就相当于synchronized (this)

静态同步方法的对象锁是类的字节码文件对象 类.class | 对象.getClass()

  1. package threadDemo;
  2.  
  3. public class ThreadDemo2 {
  4. /*
  5. * 通过验证发现同步函数,如果被静态修饰后,不再以this为锁静态进内存时,内存中没有本类的对象,
  6. * 但一定有该类的字节码文件对象 类名.class
  7. * 该对象的类型是class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
  8. */
  9. public static void main(String[] args) {
  10. Ticket t = new Ticket();
  11. Thread t1 = new Thread(t);
  12. Thread t2 = new Thread(t);
  13. // 开启第一个线程 但不一定马上执行
  14. t1.start();
  15. t.flag = false;// 改变标志
  16. try {
  17. Thread.sleep(50);
  18. } catch (Exception e) {
  19. } // 让主线程睡眠50毫秒 保证第一个线程先开始运行 且标志位改变
  20. t2.start();
  21. }
  22. }
  23. class Ticket implements Runnable {
  24. private static int ticket = 100;
  25. boolean flag = true;
  26. public void run() {
  27. if (flag) {
  28. while (true) {
  29. // synchronized(this)
  30. synchronized (Ticket.class) {
  31. if (ticket > 0) {
  32. try {
  33. Thread.sleep(50);
  34. } catch (Exception e) {
  35. }
  36. System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
  37. }
  38. }
  39. }
  40. } else
  41. while (true)
  42. show();
  43. }
  44. // 静态同步函数 该类对应的字节码文件对象为锁
  45. public static synchronized void show(){//synchronized (this)
  46. if (ticket > 0) {
  47. try {
  48. Thread.sleep(50);
  49. } catch (Exception e) {
  50. }
  51. System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
  52. }
  53. }
  54. }

运行结果:

  1. Thread-0正在出售第100张票
  2. Thread-0正在出售第99张票
  3. Thread-0正在出售第98张票
  4. Thread-0正在出售第97张票
  5. Thread-0正在出售第96张票
  6. Thread-0正在出售第95张票
  7. Thread-0正在出售第94张票
  8. Thread-0正在出售第93张票
  9. Thread-0正在出售第92张票
  10. Thread-0正在出售第91张票
  11. Thread-1正在出售第90张票
  12. Thread-1正在出售第89张票
  13. Thread-1正在出售第88张票
  14. Thread-0正在出售第87张票
  15. Thread-1正在出售第86张票
  16. Thread-1正在出售第85张票
  17. Thread-0正在出售第84张票
  18. Thread-0正在出售第83张票
  19. Thread-1正在出售第82张票
  20. Thread-1正在出售第81张票
  21. Thread-0正在出售第80张票
  22. Thread-0正在出售第79张票
  23. Thread-1正在出售第78张票
  24. Thread-0正在出售第77张票
  25. Thread-1正在出售第76张票
  26. Thread-1正在出售第75张票
  27. Thread-1正在出售第74张票
  28. Thread-0正在出售第73张票
  29. Thread-0正在出售第72张票
  30. Thread-1正在出售第71张票
  31. Thread-1正在出售第70张票
  32. Thread-1正在出售第69张票
  33. Thread-0正在出售第68张票
  34. Thread-1正在出售第67张票
  35. Thread-0正在出售第66张票
  36. Thread-0正在出售第65张票
  37. Thread-0正在出售第64张票
  38. Thread-0正在出售第63张票
  39. Thread-0正在出售第62张票
  40. Thread-1正在出售第61张票
  41. Thread-1正在出售第60张票
  42. Thread-1正在出售第59张票
  43. Thread-0正在出售第58张票
  44. Thread-0正在出售第57张票
  45. Thread-0正在出售第56张票
  46. Thread-0正在出售第55张票
  47. Thread-0正在出售第54张票
  48. Thread-0正在出售第53张票
  49. Thread-0正在出售第52张票
  50. Thread-0正在出售第51张票
  51. Thread-1正在出售第50张票
  52. Thread-1正在出售第49张票
  53. Thread-0正在出售第48张票
  54. Thread-0正在出售第47张票
  55. Thread-0正在出售第46张票
  56. Thread-0正在出售第45张票
  57. Thread-0正在出售第44张票
  58. Thread-1正在出售第43张票
  59. Thread-1正在出售第42张票
  60. Thread-0正在出售第41张票
  61. Thread-1正在出售第40张票
  62. Thread-0正在出售第39张票
  63. Thread-0正在出售第38张票
  64. Thread-0正在出售第37张票
  65. Thread-0正在出售第36张票
  66. Thread-0正在出售第35张票
  67. Thread-0正在出售第34张票
  68. Thread-0正在出售第33张票
  69. Thread-0正在出售第32张票
  70. Thread-1正在出售第31张票
  71. Thread-1正在出售第30张票
  72. Thread-1正在出售第29张票
  73. Thread-1正在出售第28张票
  74. Thread-1正在出售第27张票
  75. Thread-1正在出售第26张票
  76. Thread-1正在出售第25张票
  77. Thread-1正在出售第24张票
  78. Thread-0正在出售第23张票
  79. Thread-0正在出售第22张票
  80. Thread-0正在出售第21张票
  81. Thread-1正在出售第20张票
  82. Thread-0正在出售第19张票
  83. Thread-0正在出售第18张票
  84. Thread-0正在出售第17张票
  85. Thread-1正在出售第16张票
  86. Thread-1正在出售第15张票
  87. Thread-1正在出售第14张票
  88. Thread-1正在出售第13张票
  89. Thread-0正在出售第12张票
  90. Thread-1正在出售第11张票
  91. Thread-0正在出售第10张票
  92. Thread-0正在出售第9张票
  93. Thread-0正在出售第8张票
  94. Thread-1正在出售第7张票
  95. Thread-0正在出售第6张票
  96. Thread-0正在出售第5张票
  97. Thread-0正在出售第4张票
  98. Thread-1正在出售第3张票
  99. Thread-1正在出售第2张票
  100. Thread-0正在出售第1张票

java基础Synchronized关键字之对象锁的更多相关文章

  1. Java基础-synchronized关键字的用法(转载)

    synchronized--同步 顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 当synchronized修饰 this或者非静态方法或者是一个实例的时候,所同步的锁是加在 ...

  2. 从分布式锁角度理解Java的synchronized关键字

    分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ...

  3. 并发系列2:Java并发的基石,volatile关键字、synchronized关键字、乐观锁CAS操作

    由并发大师Doug Lea操刀的并发包Concurrent是并发编程的重要包,而并发包的基石又是volatile关键字.synchronized关键字.乐观锁CAS操作这些基础.因此了解他们的原理对我 ...

  4. Java 多线程 —— synchronized关键字

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  5. Android进阶——多线程系列之wait、notify、sleep、join、yield、synchronized关键字、ReentrantLock锁

    多线程一直是初学者最困惑的地方,每次看到一篇文章,觉得很有难度,就马上叉掉,不看了,我以前也是这样过来的.后来,我发现这样的态度不行,知难而退,永远进步不了.于是,我狠下心来看完别人的博客,尽管很难但 ...

  6. java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  7. Java的synchronized关键字:同步机制总结

    JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...

  8. Java关键字-----------------java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  9. java基础面向对象之类与对象

    java基础面向对象之类与对象 2017-01-14 1.面向对象的基本概念 以一种组建化的形式进行代码设计 1)在面向对象程序设计中包含有如下几种特性 •封装性:保护内部结构的安全性 •继承性:在已 ...

随机推荐

  1. c++:-9

    上节(c++:-8)主要学习了C++的流类库和输入输出,本节学习C++的异常处理. 异常处理 介绍 (1)异常处理的基本思想: (2)异常处理的语法: (3)举例:处理除0异常 #include &l ...

  2. 以圆类 Circle 及立体图形类 Solid 为基础设计球类 Sphere

    学习内容:以圆类 Circle 及立体图形类 Solid 为基础设计球类 Sphere 代码示例: package 实验三; import java.util.Scanner; class Point ...

  3. http协议与html

    目录 前端 HTTP协议 HTML简介 head内常见标签 body内基本标签 body内基本标签 特殊字符 布局标签(div.span) 图片标签(img) 超链接标签(a) 标签的两大重要参数(i ...

  4. Sass预处理器

    CSS预处理器 less,sass和stylus sass:较早,缩进风格 scss:完全兼容css3,使用大括号 编写css的编程语言,引入变量,函数,重复代码等功能,如果编译成css文件 Sass ...

  5. CF1580E Railway Construction

    CF1580E Railway Construction 铁路系统中有 \(n\) 个车站和 \(m\) 条双向边,有边权,无重边.这些双向边使得任意两个车站互相可达. 你现在要加一些单向边 \((u ...

  6. HTML行内元素与块级元素有哪些及区别详解

    转自 https://www.jb51.net/web/724286.html   这篇文章主要介绍了HTML行内元素与块级元素有哪些及区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具 ...

  7. 分布式机器学习:PageRank算法的并行化实现(PySpark)

    1. PageRank的两种串行迭代求解算法 我们在博客<数值分析:幂迭代和PageRank算法(Numpy实现)>算法中提到过用幂法求解PageRank. 给定有向图 我们可以写出其马尔 ...

  8. 【clickhouse专栏】新建库角色用户初始化

    一.创建新的database clickhouse创建数据库的语法几乎和其他的关系型数据库是一样的,区别就是clickhouse存在集群cluster和库引擎engine的概念,可以根据需要进行指定. ...

  9. 字符串的操作、 Math类

    字符串的操作 我们先来定义一个字符串,如果来进行过去长度,获取内容. 我们来写一个小测试! public static void main(String[] args) { String aa = & ...

  10. C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611

    09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...