博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java基础Synchronized关键字之对象锁
阅读量:6336 次
发布时间:2019-06-22

本文共 8102 字,大约阅读时间需要 27 分钟。

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()0show()1show()2show()3show()4show()5show()6show()7show()8show()9show2()0show2()1show2()2show2()3show2()4show2()5show2()6show2()7show2()8show2()9

 

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

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

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


 2.同步方法的锁是this


 

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

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

1通过当前类.class

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

 

public class ClassDemo {    void show(){        //任何一个类可以通过.class来获取字节码文件对象        Class
c = ClassDemo.class; //任何一个对象可以通过getClass()方法来获取字节码文件对象 Class
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张票

 

 

 

 

转载于:https://www.cnblogs.com/sx-jd/p/9905726.html

你可能感兴趣的文章
浅谈OS
查看>>
mac下开启docker API远程调用
查看>>
tar 命令的详解
查看>>
Cisco路由器安全配置
查看>>
第十次作业
查看>>
给定一个字符串s,返回去掉子串"mi"后的字符串。
查看>>
Nginx 外的另一选择,轻量级开源 Web 服务器 Tengine 发布新版本
查看>>
Wrod中超链接的一些技巧
查看>>
IP_VFR-4-FRAG_TABLE_OVERFLOW【cisco设备报错】碎片***
查看>>
Codeforces Round #256 (Div. 2) D. Multiplication Table 【二分】
查看>>
ARM汇编指令格式
查看>>
HDU-2044-一只小蜜蜂
查看>>
HDU-1394-Minimum Inversion Number
查看>>
df -h 卡住
查看>>
[转] createObjectURL方法 实现本地图片预览
查看>>
JavaScript—DOM编程核心.
查看>>
JavaScript碎片
查看>>
Bootstrap-下拉菜单
查看>>
soapUi 接口测试
查看>>
【c学习-12】
查看>>