zoukankan      html  css  js  c++  java
  • java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

    1.验证同步函数使用的锁----普通方法使用的锁

    • 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证。创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定。假设我们事先不知道同步函数用的是什么锁;如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题。

    看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不知道用的是什么锁?我们测试代码,看是否会发生线程安全问题。

    public class TestMethodSynchronisedLock implements Runnable {
        private int tickets = 100;
        private boolean flag = true;
        Object obj = new Object();
        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(flag){//标志位true,t1进入同步代码块
                while (true){
                    synchronized (obj) {
                        if(tickets > 0){
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+">>>>obj<<<<<"+(tickets--));
                        }
                    }
                }
            }else{
                while(true){this.show();}
                    
            }
        }
        
        public synchronized void show(){//同步函数
            while (true){
                if(tickets > 0){
                    
                    System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
                }
            }
        }
        public static void main(String[]args){
            TestMethodSynchronisedLock r = new TestMethodSynchronisedLock();
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
            t1.start();//t1启动之后进入同步代码块
            try {
                Thread.sleep(100);//主线程开启完t1,停了10毫秒,避免执行的太快,t2线程进入不了函数
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r.flag = false;//标记切换
            t2.start();//t2线程进入同步函数执行代码
        }
    }

    运行结果:

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

    出现了0票出现了线程安全问题。t1和t2不是用的同一个锁说明同步函数不是用的obj锁。

    把上面同步代码块的锁换成this,在进行测试。

    package com.lp.ecjtu.Thread;
    public class TestMethodSynchronisedLock implements Runnable {
        private int tickets = 100;
        private boolean flag = true;
        //Object obj = new Object();
        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(flag){//标志位true,t1进入同步代码块
                while (true){
                    synchronized (this) {//同步代码块,obj改为this证明同步代码块和下面的同步函数调用的是this锁
                        if(tickets > 0){
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+">>>>obj<<<<<"+(tickets--));
                        }
                    }
                }
            }else{
                while(true){this.show();}
                    
            }
        }
        
        public synchronized void show(){//同步函数
            while (true){
                if(tickets > 0){
                    
                    System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
                }
            }
        }
        public static void main(String[]args){
            TestMethodSynchronisedLock r = new TestMethodSynchronisedLock();
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
            t1.start();//t1启动之后进入同步代码块
            try {
                Thread.sleep(100);//主线程开启完t1,停了10毫秒,避免执行的太快,t1线程进入不了synchronized代码块
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r.flag = false;//标记切换
            t2.start();//2线程进入同步函数代码块
        }
    }

    运行结果如下:

    Thread-0>>>>obj<<<<<100
    Thread-0>>>>obj<<<<<99
    Thread-0>>>>obj<<<<<98
    Thread-1>>>>show<<<<<97
    Thread-1>>>>show<<<<<96
    Thread-1>>>>show<<<<<95
    Thread-1>>>>show<<<<<94
    Thread-1>>>>show<<<<<93
    Thread-1>>>>show<<<<<92
    Thread-1>>>>show<<<<<91
    Thread-1>>>>show<<<<<90
    Thread-1>>>>show<<<<<89
    Thread-1>>>>show<<<<<88
    Thread-1>>>>show<<<<<87
    Thread-1>>>>show<<<<<86
    Thread-1>>>>show<<<<<85
    Thread-1>>>>show<<<<<84
    Thread-1>>>>show<<<<<83
    Thread-1>>>>show<<<<<82
    Thread-1>>>>show<<<<<81
    Thread-1>>>>show<<<<<80
    Thread-1>>>>show<<<<<79
    Thread-1>>>>show<<<<<78
    Thread-1>>>>show<<<<<77
    Thread-1>>>>show<<<<<76
    Thread-1>>>>show<<<<<75
    Thread-1>>>>show<<<<<74
    Thread-1>>>>show<<<<<73
    Thread-1>>>>show<<<<<72
    Thread-1>>>>show<<<<<71
    Thread-1>>>>show<<<<<70
    Thread-1>>>>show<<<<<69
    Thread-1>>>>show<<<<<68
    Thread-1>>>>show<<<<<67
    Thread-1>>>>show<<<<<66
    Thread-1>>>>show<<<<<65
    Thread-1>>>>show<<<<<64
    Thread-1>>>>show<<<<<63
    Thread-1>>>>show<<<<<62
    Thread-1>>>>show<<<<<61
    Thread-1>>>>show<<<<<60
    Thread-1>>>>show<<<<<59
    Thread-1>>>>show<<<<<58
    Thread-1>>>>show<<<<<57
    Thread-1>>>>show<<<<<56
    Thread-1>>>>show<<<<<55
    Thread-1>>>>show<<<<<54
    Thread-1>>>>show<<<<<53
    Thread-1>>>>show<<<<<52
    Thread-1>>>>show<<<<<51
    Thread-1>>>>show<<<<<50
    Thread-1>>>>show<<<<<49
    Thread-1>>>>show<<<<<48
    Thread-1>>>>show<<<<<47
    Thread-1>>>>show<<<<<46
    Thread-1>>>>show<<<<<45
    Thread-1>>>>show<<<<<44
    Thread-1>>>>show<<<<<43
    Thread-1>>>>show<<<<<42
    Thread-1>>>>show<<<<<41
    Thread-1>>>>show<<<<<40
    Thread-1>>>>show<<<<<39
    Thread-1>>>>show<<<<<38
    Thread-1>>>>show<<<<<37
    Thread-1>>>>show<<<<<36
    Thread-1>>>>show<<<<<35
    Thread-1>>>>show<<<<<34
    Thread-1>>>>show<<<<<33
    Thread-1>>>>show<<<<<32
    Thread-1>>>>show<<<<<31
    Thread-1>>>>show<<<<<30
    Thread-1>>>>show<<<<<29
    Thread-1>>>>show<<<<<28
    Thread-1>>>>show<<<<<27
    Thread-1>>>>show<<<<<26
    Thread-1>>>>show<<<<<25
    Thread-1>>>>show<<<<<24
    Thread-1>>>>show<<<<<23
    Thread-1>>>>show<<<<<22
    Thread-1>>>>show<<<<<21
    Thread-1>>>>show<<<<<20
    Thread-1>>>>show<<<<<19
    Thread-1>>>>show<<<<<18
    Thread-1>>>>show<<<<<17
    Thread-1>>>>show<<<<<16
    Thread-1>>>>show<<<<<15
    Thread-1>>>>show<<<<<14
    Thread-1>>>>show<<<<<13
    Thread-1>>>>show<<<<<12
    Thread-1>>>>show<<<<<11
    Thread-1>>>>show<<<<<10
    Thread-1>>>>show<<<<<9
    Thread-1>>>>show<<<<<8
    Thread-1>>>>show<<<<<7
    Thread-1>>>>show<<<<<6
    Thread-1>>>>show<<<<<5
    Thread-1>>>>show<<<<<4
    Thread-1>>>>show<<<<<3
    Thread-1>>>>show<<<<<2
    Thread-1>>>>show<<<<<1
    多次运行分析,线程安全,说明同步代码块和同步函数运行的锁是一样的。总结:函数被对象引用,那么函数都一个所属对象的引用,就是this,所以同步函数使用的锁是this。

    2.验证同步函数使用的锁----静态方法使用的锁

    思路和上面验证普通方法的思路一样。直接给出结论:

    静态方法使用的锁是该方法所在的类的字节码文件对象( 类名.class)
     * 通过验证,发现不是this,因为静态方法中不可以定义this
     * 静态变量存放在内存共享区域内,而对象是存放在堆内存中。
     * 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码的文件对象。
     * 类名.class

    public class TestStaticMethodSynchronisedLock implements Runnable {
        private static int tickets = 100;
        private boolean flag = true;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(flag){
                while (true){
                    synchronized (TestStaticMethodSynchronisedLock.class) {//静态方法用的锁是类字节码文件对象(类.class)
                        if(tickets > 0){
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+">>>>code<<<<<"+(tickets--));
                        }
                    }
                }
            }else{
                while(true){this.show();}
                    
            }
        }
        
        public static synchronized void show(){//同步函数
            while (true){
                if(tickets > 0){
                    System.out.println(Thread.currentThread().getName()+">>>>show<<<<<"+(tickets--));
                }
            }
        }
        public static void main(String[]args){
            TestStaticMethodSynchronisedLock r = new TestStaticMethodSynchronisedLock();
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
            t1.start();
            try {
                Thread.sleep(100);//主线程停了10毫秒,避免执行的太快,t1线程进入不了synchronized代码块
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r.flag = false;
            t2.start();
        }
    }

    运行结果,是线程安全的。

     
  • 相关阅读:
    ResponsiveSlides.js最轻量级的幻灯片插件
    jQuery.extend 函数详解
    HQL查询语言的使用介绍
    使用Hibernate命名查询
    Jquery.KinSlideshow图片轮播插件
    关于文件下载自己忽略的文件中文命名。。。
    DB2中的ROW_NUMBER() OVER()函数用法
    css ul li 水平布局问题
    彻底弄懂css中单位px和em,rem的区别 转的自己看
    taglib 自定义标签
  • 原文地址:https://www.cnblogs.com/200911/p/3900162.html
Copyright © 2011-2022 走看看