java中Synchronized关键字之对象锁

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

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

  语法:Synchronized(对象锁){}

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

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

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


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


package threadDemo;

public class ThreadDemo
{
public static void main(String[] args)
{
Example example = new Example(); Thread t1 = new TH(example);
Thread t2 = new TH(example); t1.start();
t2.start();
} } class Example
{
public synchronized void show()
{
for (int i = 0; i < 10; ++i)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(i);
}
} } class TH extends Thread
{
private Example example; public TH(Example example)
{
this.example = example;
} @Override
public void run()
{
example.show();
} }

运行结果:

show()0
show()1
show()2
show()3
show()4
show()5
show()6
show()7
show()8
show()9
show2()0
show2()1
show2()2
show2()3
show2()4
show2()5
show2()6
show2()7
show2()8
show2()9

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

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

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


2.同步方法的锁是this


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

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

1通过当前类.class

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

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

验证同步方法的对象锁是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-- + "张票");
}
}

}

运行结果:

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

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

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

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

package threadDemo;

public class ThreadDemo2 {
/*
* 通过验证发现同步函数,如果被静态修饰后,不再以this为锁静态进内存时,内存中没有本类的对象,
* 但一定有该类的字节码文件对象 类名.class
* 该对象的类型是class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
*/
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
// 开启第一个线程 但不一定马上执行
t1.start();
t.flag = false;// 改变标志
try {
Thread.sleep(50);
} catch (Exception e) {
} // 让主线程睡眠50毫秒 保证第一个线程先开始运行 且标志位改变
t2.start();
}
}
class Ticket implements Runnable {
private static int ticket = 100;
boolean flag = true;
public void run() {
if (flag) {
while (true) {
// synchronized(this)
synchronized (Ticket.class) {
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}
}
} else
while (true)
show();
}
// 静态同步函数 该类对应的字节码文件对象为锁
public static synchronized void show(){//synchronized (this)
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + ticket-- + "张票");
}
}
}

运行结果:

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

    学习内容:随机数 1.GetEvenNum()方法 实例代码: package 数字处理类; public class MathRondom {public static int GetEvenNum ...

  2. 记一次Tomcat卡死在 Deploying web application 步骤的问题

    公司有一个历史的遗留项目是传统的MVC架构的前后不分离的项目,一开始使用JDK1.7写的,后来前一阵老板说想在这个远古项目上加点功能,顺带换换皮,于是乎一帮程序员们就用JDK1.8重新翻新了一遍项目顺 ...

  3. Citrix Virtual Apps and Desktops 7 2203 LTSR虚拟云桌面单机教程

    哈喽大家好,欢迎来到虚拟化时代君(XNHCYL). 大家好,我是虚拟化时代君,一位潜心于互联网的技术宅男.这里每天为你分享各种你感兴趣的技术.教程.软件.资源.福利--(每天更新不间断) 一 .主要内 ...

  4. Java基本运算

    目录 运算符 运算符优先级 运算 自增(++)自减(--)运算 数学运算(Math类) 逻辑运算 位运算 拓展运算符 三元运算符 视频课程 运算符 Java语言支持如下运算符: 算术运算符: +, - ...

  5. App上看到就忍不住点的小红点是如何实现的?

    你有没有发现,我们解锁手机后桌面上App右上角总能看到一个小红点,这就是推送角标.推送角标指的是移动设备上App图标右上角的红色圆圈,圆圈内的白色数字表示未读消息数量.角标是一种比较轻的提醒方式,通过 ...

  6. 【zigbee无线通信模块步步详解】ZigBee3.0模块建立远程网络控制方法

    本文以路灯控制应用为例,简述ZigBee3.0模块使用流程. 一.建立网络 1.通过USB转串口模块将出厂的ZigBee自组网模块连接,打开上位机软件"E180-ZG120A-Setting ...

  7. .NET C#基础(6):命名空间 - 有名字的作用域

    0. 文章目的   面向C#新学者,介绍命名空间(namespace)的概念以及C#中的命名空间的相关内容. 1. 阅读基础   理解C与C#语言的基础语法.   理解作用域概念. 2. 名称冲突与命 ...

  8. 送分题,ArrayList 的扩容机制了解吗?

    1. ArrayList 了解过吗?它是啥?有啥用? 众所周知,Java 集合框架拥有两大接口 Collection 和 Map,其中,Collection 麾下三生子 List.Set 和 Queu ...

  9. Idea创建文件夹自动合成一个

    在idea中创建文件夹时,它们总是自动合成一个,如下图: 文件夹自动折叠真的很影响效率,可能会引发一些不经意的失误 解决方法: 取消这个地方的勾选 这样就可以正常创建文件夹了

  10. Spring框架系列(3) - 深入浅出Spring核心之控制反转(IOC)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点; 本节将在此基础上进一步解读IOC的含义以及IOC的使用方式.@pd ...