并发编程四:Synchronized关键字

    xiaoxiao2025-03-06  12

    # 并发编程之: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/

    转载请注明原文地址: https://ju.6miu.com/read-1296952.html
    最新回复(0)