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();

    }

}

 

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

 

你可能感兴趣的:(java多线程)