java 多线程10:synchronized锁机制 之 锁定类静态方法 和锁定类.Class 和 数据String的常量池特性...

同步静态方法

synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁。看一下例子,注意一下printC()并不是一个静态方法:

public class ThreadDomain25
{
    public synchronized static void printA()
    {
        try
        {
            System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                    "在" + System.currentTimeMillis() + "进入printA()方法");
            Thread.sleep(3000);
            System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                    "在" + System.currentTimeMillis() + "离开printA()方法");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    public synchronized static void printB()
    {
        System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                "在" + System.currentTimeMillis() + "进入printB()方法");
        System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                "在" + System.currentTimeMillis() + "离开printB()方法");

    }
    
    public synchronized void printC()
    {
        System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                "在" + System.currentTimeMillis() + "进入printC()方法");
        System.out.println("线程名称为:" + Thread.currentThread().getName() + 
                "在" + System.currentTimeMillis() + "离开printC()方法");
    }
}

写三个线程分别调用这三个方法:

public class MyThread25_0 extends Thread
{
    public void run()
    {
        ThreadDomain25.printA();
    }
}
public class MyThread25_1 extends Thread
{
    public void run()
    {
        ThreadDomain25.printB();
    }
}
public class MyThread25_2 extends Thread
{
    private ThreadDomain25 td;
    
    public MyThread25_2(ThreadDomain25 td)
    {
        this.td = td;
    }
    
    public void run()
    {
        td.printC();
    }
}

写个main函数启动这三个线程:

public static void main(String[] args)
{
    ThreadDomain25 td = new ThreadDomain25();
    MyThread25_0 mt0 = new MyThread25_0();
    MyThread25_1 mt1 = new MyThread25_1();
    MyThread25_2 mt2 = new MyThread25_2(td);
    mt0.start();
    mt1.start();
    mt2.start();
}

看一下运行结果:

线程名称为:Thread-0在1443857019710进入printA()方法
线程名称为:Thread-2在1443857019710进入printC()方法
线程名称为:Thread-2在1443857019710离开printC()方法
线程名称为:Thread-0在1443857022710离开printA()方法
线程名称为:Thread-1在1443857022710进入printsynchronized B()方法
线程名称为:Thread-1在1443857022710离开printB()方法

从运行结果来,对printC()方法的调用和对printA()方法、printB()方法的调用时异步的,这说明了静态同步方法和非静态同步方法持有的是不同的锁,前者是类锁,后者是对象锁

所谓类锁,举个再具体的例子。假如一个类中有一个静态同步方法A,new出了两个类的实例B和实例C,线程D持有实例B,线程E持有实例C,只要线程D调用了A方法,那么线程E调用A方法必须等待线程D执行完A方法,尽管两个线程持有的是不同的对象。

 

同步类.Class
同步synchronized(class) 和同步静态方法都是一样,同步的都是当前的类锁 

类Service




结果


实验证明  静态方法  和静态类.class 锁 都是一样获取的类锁




数据String的常量池特性
在使用同步的时候,如果要锁定String , 两个线程运行的时候,很可能有一个无限等待无法获取到锁





这里就是String 常量池带来的奇葩问题 , 要特别注意







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值