并发编程四:Synchronized关键字

# 并发编程之:Synchronized #

介绍

由于Java对多线程编程的支持,因此在编写多线程代码时是会出现对资源共享导致不安全操作的. 
因此Java提供了Synchronized关键字来保证同步操作,所谓同步操作指的是:同一时刻只有一个线程能够访问的操作。

Java同步关键字Synchronized

Java中的同步块用synchronized标记。同步块在Java中是同步在某个对象上。 
所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。 
所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块中的线程退出。

四种不同的同步块:
1、实例方法
2、静态方法
3、实例方法中的同步块
4、静态方法中的同步块

实例方法同步

private int count;
public synchronized int incr(int num)
{
    return (count + num);
}

Java实例方法同步是同步在其拥有该方法的对象上。
每个实例其方法同步都同步在不同的对象上,即该方法所属的实例。

静态方法同步

// 调用次数
private static int reqeust_times;
public static synchronized int count()
{
    return ++reqeust_times;
}

静态方法的同步是指同步在该方法所在的类对象上。类对象:Java中每个类都有其唯一对应的Class实例。

在静态方法中使用同步效率是比较低下的要慎重使用。

实例方法中同步代码块

public int incr(int num)
{
    synchronized (this)
    {
        return (count + num);
    }
}
该方式和同步在实例方法是等效的。
this表示的就是当前实例对象

synchronized代码块使用形式

synchronized(Object obj){

    //...操作代码
}

obj可以是任意对象,表示监视器对象

开发多线程并发时,要注意同步对象是否一致,然后再分析。

Java同步实例

Counter Code

public class Counter
{

    private int count = 0;

    public int incr()
    {
        synchronized (this)
        {
            return (++count);
        }
    }

    // 调用次数
    private static int reqeust_times;

    public static synchronized int count()
    {
        return ++reqeust_times;
    }

}

CounterThread线程

public class CounterThread implements Runnable
{

    //Counter对象
    private Counter counter;

    public CounterThread(Counter counter)
    {
        this.counter = counter;
    }

    @Override
    public void run()
    {
        for (int i = 0; i < 5; i++)
        {
            System.out.println(Thread.currentThread().getName() + "-----" + counter.incr());
        }
    }
}

Main方法

public class Main
{

    public static void main(String[] args)
    {

        Counter counter = new Counter();

        CounterThread counterThread1 = new CounterThread(counter);
        CounterThread counterThread2 = new CounterThread(counter);

        new Thread(counterThread1, "线程1").start();
        new Thread(counterThread2, "线程2").start();

        // 结果是两个线程是同步交替执行incr方法的

        // Counter counter1 = new Counter();
        // Counter counter2 = new Counter();
        //
        // CounterThread counterThread1 = new CounterThread(counter1);
        // CounterThread counterThread2 = new CounterThread(counter2);
        //
        // new Thread(counterThread1, "线程1").start();
        // new Thread(counterThread2, "线程2").start();
        // 结果就是各自跑各自的不会互相影响

    }
}


备注:自己多倒腾一下,颠来倒去的试试就理解了。当然一些原理性的知识点一定要掌握和记住。

总结

Synchronized关键字同步机制,是jvm底层提供实现的,使用起来通常不会出现严重性bug,但是相对Lock来说性能和灵活性会差一些.

关于使用Synchronized还是并发包下的Lock锁实现并没有严格要求,看场景需求,大部分情况下请使用Lock锁实现.灵活性和细粒度控制。

注意: Synchronized实现了可重入锁功能。

参考

1、https://www.ibm.com/developerworks/cn/java/j-jtp10264/
2、http://tutorials.jenkov.com/java-concurrency/synchronized.html
3、https://www.ibm.com/developerworks/cn/java/j-lo-deadlock/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值