从使用synchronized同步锁到AtomicInteger原子操作

简介: 从使用synchronized同步锁到AtomicInteger原子操作

有一个场景需要实现多线程处理任务完毕后,再串行处理后面的流程。


下面首先介绍的方式,是通过synchronized同步锁来实现,这是一种最基础的方式,后面的文章,我整理其他其他更丰富的方法。


通过synchronized同步锁来实现:


就是放置一个公用的static变量,假如有10个线程,每个线程处理完上去累加下结果,然后后面用一个死循环(或类似线程阻塞的方法),去数这个结果,达到10个,说明大家都执行完了,就可以执行后续的事情了,这个想法虽然土鳖,但是基本上跟语言无关,几乎所有主流编程语言都支持。


下面直接上代码:

public class ThreadLockTest {
    public static Integer flag = 0;//公用变量
    public static void main(String[] args) throws Exception {
        ThreadLockTest testObj = new ThreadLockTest();
        final int threadNum = 10;
        for (int i = 0; i < threadNum; i++) {
            new Thread(new MyRunable(i, testObj)).start();
        }
        while (true) {
            if (testObj.flag >= threadNum) {
                System.out.println("-----------\n所有thread执行完成!");
                break;
            }
            Thread.sleep(10);
        }
    }
    static class MyRunable implements Runnable {
        int _i = 0;
        ThreadLockTest _test;
        public MyRunable(int i, ThreadLockTest test) {
            this._i = i;
            this._test = test;
        }
        @Override
        public void run() {
            try {
                Thread.sleep((long) (Math.random() * 10));
                System.out.println("thread " + _i + " done");
                //利用synchronized获得同步锁
                synchronized (_test) {
                    _test.flag += 1;
                }
                System.out.println("thread " + _i + " => " + _test.flag);//测试用
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


可以看到上面使用synchronized获得同步锁的处理类似下面的代码,其中必须加上synchronized是为了证不会出现并发线程同时访问的情况。

public class Sample1 {
    private static Integer count = 0;
    synchronized public static void increment() {
        count++;
    }
}


升级开始,下面再来看一段代码:

public class Sample2 {
    private static AtomicInteger count = new AtomicInteger(0);
    public static void increment() {
        count.getAndIncrement();
    }
}


上面使用AtomicInteger中却不用加上synchronized,因为AtomicInteger是一个提供原子操作的Integer类,它是通过线程安全的方式操作加减,因此十分适合高并发情况下的使用。


两相对比下来,是不是使用AtomicInteger更简单呢。下面咱就对最上面的代码,使用AtomicInteger优化调整一下,于是就有了下面的代码:

import java.util.concurrent.atomic.AtomicInteger;
public class ThreadAtomTest {
    public static AtomicInteger atomicInteger = new AtomicInteger(0);
    public static void main(String[] args) throws Exception {
        final int threadNum = 10;
        for (int i = 0; i < threadNum; i++) {
            new Thread(new ThreadAtomTest.MyRunable(i)).start();
        }
        while (true) {
            if (ThreadAtomTest.atomicInteger.intValue() >= threadNum) {
                System.out.println("-----------\n所有thread执行完成!");
                break;
            }
            Thread.sleep(10);
        }
    }
    static class MyRunable implements Runnable {
        int _i = 0;
        public MyRunable(int i) {
            this._i = i;
        }
        @Override
        public void run() {
            try {
                Thread.sleep((long) (Math.random() * 10));
                System.out.println("thread " + _i + " done");
                int andIncrement = ThreadAtomTest.atomicInteger.incrementAndGet();
                System.out.println("thread " + _i + " => " + andIncrement);//测试用
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


相关文章
|
2月前
|
算法 Java 编译器
Synchronized你又知道多少?
Synchronized 是 JVM 实现的一种互斥同步机制,通过 monitorenter 和 monitorexit 指令控制对象锁的获取与释放。锁的本质是对象头的标记,确保同一时间只有一个线程访问资源。Synchronized 支持可重入性,允许方法内部调用其他同步方法而不阻塞。JVM 对锁进行了优化,引入了自旋锁、偏向锁、轻量级锁和重量级锁,以减少系统开销。Synchronized 属于悲观锁,而乐观锁基于 CAS(Compare and Swap)算法实现非阻塞同步,提高并发性能。
61 6
|
4月前
多线程线程安全问题之synchronized和ReentrantLock在锁的释放上有何不同
多线程线程安全问题之synchronized和ReentrantLock在锁的释放上有何不同
|
6月前
|
存储 安全 Java
|
安全 算法 Java
synchronized 同步锁
Java中的synchronized关键字用于实现线程同步,可以修饰方法或代码块。 1. 修饰方法:当一个方法被synchronized修饰时,只有获得该方法的锁的线程才能执行该方法。其他线程需要等待锁的释放才能执行该方法。 2. 修饰代码块:当某个对象被synchronized修饰时,任何线程在执行该对象中被synchronized修饰的代码块时,必须先获得该对象的锁。其他线程需要等待锁的释放才能执行同步代码块。Java中的每个对象都有一个内置锁,当一个对象被synchronized修饰时,它的内置锁就起作用了。只有获得该锁的线程才能访问被synchronized修饰的代码段。使用synch
62 0
|
安全 Java
synchronized 锁与 ReentrantLock 锁的区别
synchronized 锁与 ReentrantLock 锁的区别
110 0
|
存储 缓存 安全
【Synchronized】
【Synchronized】
141 0
【Synchronized】
synchronized 锁的是什么?(二)
每个对象都存在着一个 Monitor 对象与之关联。执行 monitorenter 指令就是线程试图去获取 Monitor 的所有权,抢到了就是成功获取锁了;执行 monitorexit 指令则是释放了 Monitor 的所有权。
synchronized 锁的是什么?(二)
多线程 - Synchronized 篇(一)
多线程 - Synchronized 篇(一)
74 0
多线程 - Synchronized 篇(一)
多线程 - Synchronized 篇(四)
多线程 - Synchronized 篇(四)
86 0
多线程 - Synchronized 篇(四)