ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

并发编程(叁):synchronize

2019-07-02 10:00:55  阅读:178  来源: 互联网

标签:加锁 synchronized 并发 结果 void 编程 synchronize 线程 public


synchronize


synchronized是Java中的关键字,是一种常用的线程同步锁。

用法

注意:在理解synchronized时,要知道一个核心点,synchronized锁定的不是代码,而是对象。使用synchronized时,其会申请对象的堆内存,进行锁定。

写法一

    Object o = new Object(); // 锁对象
    public void test01(){
        //任何线程要执行以下的代码,必须先拿到锁
        synchronized (o){  
            // doSomething...
        }
    }

写法二

上述写法是创建一个锁对象,其实可以自身作为锁对象。

    public void test02(){
        synchronized (this){ 
            // doSomething...
        }
    }

写法三

同写法二。

    public synchronized void test03(){
        // doSomething...
    }

写法四

锁定静态方法。静态方法是属于类方法,没有对象。

    public synchronized static void test04(){
    }

写法五

同写法四

    public static void test04(){
        synchronized (SynchronizeTest.class){
        }
    }

测试线程安全问题

演示代码:

public class RunnableDemo implements Runnable {

    private int count = 10;

    @Override
    public /*synchronized*/ void run() {
        count--;
        System.out.println(Thread.currentThread().getName() + "count=" + count);
    }

    public static void main(String[] args) {
        RunnableDemo t = new RunnableDemo();
        for (int i = 0; i < 8; i++) {
            new Thread(t, "结果是:" + i).start();
        }
    }
}

结果是:

结果是:1count=9
结果是:0count=8
结果是:2count=7
结果是:3count=6
结果是:5count=5
结果是:4count=4
结果是:6count=3
结果是:7count=2

加入synchronized:

结果是:0count=9
结果是:1count=8
结果是:2count=7
结果是:3count=6
结果是:4count=5
结果是:5count=4
结果是:6count=3
结果是:7count=2

可以看到输出顺序是不一样的.

注意事项

在实际业务场景中,往往将读方法不加锁,写的方法加锁,这样会导致一个问题,也就是读的数据是写之前的数据,导致脏读问题。解决方案就是,在读方法上也加锁

  1. 加锁方法不影响不加锁方法的执行;

  2. 加锁方法访问另外一个加锁方法,一个线程拥有某个对象的锁,再次申请的时候可以再次得到这把锁(相当于锁上了两把同样的锁);子类的同步方法调用父类的同步方法也可以;

  3. synchronized 遇到异常,锁会被释放。如果不想该锁被释放,就直接catch;

  4. 不要以字符串常量作为锁对象。
public class StringAsSynchObject {
    private String stra = "hello";
    private String strb = "hello";
    void test1(){
        synchronized (stra){
        }
    }
    void test2(){
        synchronized (strb){
        }
    }
}

在上述代码中,因为stra和strb 锁的是同一个对象,如果用到了同一个类库,在该类库中的代码锁定了字符串"hello",我们读不到源码,而在业务代码中也锁定了同样的字符串,这就有可能会造成非常诡异的死锁阻塞。因为程序和类库不经意用了同一把锁。(这种情况一般没办法调试)。所以通常不要字符串作为锁定对象。

  1. synchronize 锁定的粒度越小(即锁定的业务代码越少),效率越高。
  2. synchronize 锁释放的情况:

    1)线程执行完毕;

    2)线程发生异常;

    3)线程进入休眠状态。
  3. synchronize 是互斥锁,可重入锁。
  4. wait()和notify()/notifyAll() 与 synchronize同时出现。

标签:加锁,synchronized,并发,结果,void,编程,synchronize,线程,public
来源: https://www.cnblogs.com/xzy-/p/11118652.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有