Java 锁

1.锁的对象是什么?

对于普通同步方法,锁是当前实例对象。

对于静态同步方法,锁是当前类的Class对象(可以理解为锁的类模板)。

对于同步方法块,锁是Synchonized括号里配置的对象

首先定义一个资源类 

class South{
    // synchronized 锁的对象是方法的调用者!、
    // 两个方法用的是同一个锁,谁先拿到谁执行!
    public synchronized void run1(){
        System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
    }
    public synchronized void run2(){
        System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
    }
    public void run3(){
        System.out.println("无锁的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
    }
    public static synchronized void run4(){
        System.out.println(Thread.currentThread().getName() + "成功创建!执行时间:" + System.currentTimeMillis() );
        try {
            TimeUnit.SECONDS.sleep(4);
            System.out.println(Thread.currentThread().getName() + "线程暂停4秒!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("静态syn的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
    }
    public static synchronized void run5(){
        System.out.println("静态syn的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
    }
}

普通方法进行加锁 对于普通同步方法,锁是当前实例对象

 @Test
    public void test1(){
        South south = new South();
        new Thread(() -> south.run1(),"A线程").start();
        new Thread(() -> south.run2(),"B线程").start();
        try {  // 让主线程等待子线程,否则主线程(main线程)结束后,子线程的打印无法在控制台看到
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }  
@Test
    public void test2(){
        South south1 = new South();
        South south2 = new South();
        new Thread(() -> south1.run1(),"A线程").start();
        new Thread(() -> south2.run2(),"B线程").start();
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    } 
  运行结果 总结 个人理解
test1

A线程执行了!执行时间:1617866326536

# sleep(4)
A线程执行了!执行时间:1617866330537
B线程执行了!执行时间:1617866330537

结果:B线程等待A线程结束后才执行

总结:多线程操作同一个资源,synchronized 锁的资源的调用者 即(当前实例对象) this,new South 的 south,两个线程是共用同一把锁,谁先得到锁,谁先执行 。

 

A 首先获取的 this 并加锁,B 线程也尝试加锁,由于 syn 为独占锁,所以B 线程加锁失败被挂起,A 线程执行结束后被唤醒继续执行。 

test2

A线程执行了!执行时间:1617866385192

# A线程休眠中
B线程执行了!执行时间:1617866385192
A线程执行了!执行时间:1617866389193

结果:B线程等待A线程几乎是同时执行的

总结:多线程操作不同资源,线程之间的 synchronized 锁不影响(synchronized 锁的资源的调用者

A 、B 两个线程获取的不是同一个资源

普通方法加锁与无锁方法对比

@Test
    public void test3(){
        South south = new South();
        new Thread(() -> south.run1(),"A线程").start();
        new Thread(() -> south.run3(),"B线程").start();
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

 

不同的资源对象,普通方法加锁、无锁与 静态方法 加锁方法对比 

@Test
    public void test4(){
        South south1 = new South();
        South south2 = new South();
        South south3 = new South();
        System.out.println(Thread.currentThread().getName()+ "执行了!执行时间:" +System.currentTimeMillis());
        new Thread(() -> south1.run4(),"A线程").start();
        new Thread(() -> south2.run3(),"B线程").start();
        new Thread(() -> south3.run5(),"c线程").start();
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

 

同一的资源对象,普通静态方法加锁 

@Test
    public void test5(){
        South south1 = new South();
        System.out.println(Thread.currentThread().getName()+ "执行了!执行时间:" +System.currentTimeMillis());
        new Thread(() -> south1.run4(),"A线程").start();
        new Thread(() -> south1.run2(),"B线程").start();
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
全部评论

相关推荐

在校生实习:我觉得平时学校肯定有各种大作业吧。包装一下写项目里。特长那块喧宾夺主了,项目肯定是大头。特长里比如:熟悉vscode,这个感觉不具有吸引性。简要介绍你会什么语言,什么工具等就行了。同26找实习,我是个超级菜鸡😭大家一起加油
点赞 评论 收藏
分享
10-30 10:16
南京大学 Java
龚至诚:给南大✌️跪了
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务