synchronized 类 ,对象 ,以及方法的解析

java中的synchronized 关键字,想必大部分人还是了解的,就是同步。主要目的是什么呢?:避免多线程共享资源的不安全。什么意思呢?因为如果存在多线程共享资源的时候,很容易出现不安全性。比如下面一段代码就是不安全的:

public class ThreadTest {

    private int ticket = 3;

    private void buyTicket() {
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket--;
            System.out.println(Thread.currentThread().getName() + ":买到,余票为" + ticket);
        } else {
            System.out.println(Thread.currentThread().getName() + ":没买到,余票为" + ticket);
        }

    }

    public static void main(String[] args) {
        final ThreadTest test = new ThreadTest();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                for(int i=0;i<3;i++){
                    test.buyTicket();
                }
            }
        }, "t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                for(int i=0;i<3;i++){
                    test.buyTicket();
                }
            }
        }, "t2");
        t1.start();
        t2.start();

    }

}

执行的结果为:

t1:买到,余票为2
t2:买到,余票为1
t2:买到,余票为0
t2:没买到,余票为0
t1:买到,余票为-1
t1:没买到,余票为-1

例子很实用,就是我们现实生活中的买票,因为卖票点有非常多在同时操作,而票的余量是固定的。这里每个卖票的窗口就像是一个线程,票的余量就是共享的资源。很明显我们分析打印就知道很可笑:其中出现了4次买到,但是只有3张票,所以这是线程不安全的。那如何解決呢?我们可以在买票的方法中加上同步锁,代码如下:

    private void buyTicket() {
        synchronized (this) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticket--;
                System.out.println(Thread.currentThread().getName() + ":买到,余票为" + ticket);
            } else {
                System.out.println(Thread.currentThread().getName() + ":没买到,余票为" + ticket);
            }
        }
    }

其他不变,我们看输出:

t1:买到,余票为2
t2:买到,余票为1
t1:买到,余票为0
t1:没买到,余票为0
t2:没买到,余票为0
t2:没买到,余票为0

这样程序就输出正常了。解决了不安全的问题。这就是synchronized 的作用以及简单用法。

今天我们要讲的当然不只是这些,因为我们常常在使用synchronized 有很多种用法,下面是一些常用的:

synchronized (this) { ... }

synchronized (object) { ... }

public synchronized void fuction(){
}

synchronized (object.class) { ... }

public static synchronized void fuction(){
}

其中注意的有几种用法:
1. 同一个对象调用了具有同步关键字的代码块
2. 不同的对象调用了具有同步关键子的代码块
3. 同一个对象同时调用了含有不同同步代买块的方法。
4. 不同对象调用了含有不同不同步方法的代码块

如下表:

类型同一个对象中多次调用不同的对象中多次调用同一个对象与其他类型同步类型混用不同的对象与其他类型同步类型混用
synchronized (object)会阻塞不会阻塞synchronized (this)不会,synchronized (object)如果object是同一个对象会阻塞,public synchronized void fuction()不会阻塞synchronized (this)不会,synchronized (object)如果object是同一个对象会阻塞,public synchronized void fuction()不会阻塞
synchronized (this)会阻塞不会阻塞synchronized (this)会,synchronized (object)不会,public synchronized void fuction()会阻塞synchronized (this)不会,synchronized (object)不会,public synchronized void fuction()不会阻塞
public synchronized void fuction()会阻塞不会阻塞synchronized (this)会,synchronized (object)不会,public synchronized void fuction()会阻塞synchronized (this)会,synchronized (object)不会,public synchronized void fuction()会阻塞
synchronized (object.class)会阻塞会阻塞synchronized (object.class)不会,public static synchronized void fuction()会阻塞synchronized (object.class)会,public synchronized void fuction()会阻塞,public static synchronized void fuction()会阻塞
public static synchronized void fuction()会阻塞会阻塞synchronized (object.class)会,public static synchronized void fuction()会阻塞synchronized (object.class)会,public static synchronized void fuction()会阻塞

前三种属于一类,后面两种属于一类,这两类混用不起任何效果。
这里就补一个一个测试了。表述一下总结把:
1.synchronized (object) { … } 这种作用最小,只有同步的对象是同一个的时候才会起作用,并且当他所在的类存在 synchronized (this) { … } 、public synchronized void fuction(){} 的时候是互不相关的
2.synchronized (object.class) { … } 这种作用和 public static synchronized void fuction(){} 作用类似,同步的是所有这个类的对象,针对不同实例调用次方法是都会被阻塞。static 方法就是一个,所以不管是哪个实例调用,最终都是同一个,所以肯定会阻塞的。
3.synchronized (this) { … } 同步的是当前的这个类的对象。值得注意的是,当他和同步方法一起使用的时候其中后执行的一个会被阻塞

好了到这里我们同步锁讲的差不多了,但是我们还要知道,加了同步锁的代码会造成阻塞,所以我们在使用的时候一定要注意场景,防止过多的实现消耗。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值