小白的多线程修行之路1(共享变量与不共享变量)

本人,小白一枚,以下是我自己学习过程中所做的一些研究,如果有错误之处,还请指出来,我会及时改正,谢谢哈!!!

自定义线程类中的变量与其他线程可以有共享与不共享之分:

(1)不共享数据的情况

如下例所示:

通过线程池去创建三个线程,也可采用其他的形式,这里所使用的是线程池去创建线程,每个线程都有自己的count变量,即try块中的count变量,每个线程自己减少自己的count变量,这样情况下就是变量不共享。

public class ThreadTest {
//    private static volatile int count = 5;
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        ExecutorService executorService = new ThreadPoolExecutor(
                5,5,10,
                TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5));
        for(int i=0;i<3;i++){
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    int count = 5;
                    System.out.println(Thread.currentThread().getName()+"进入run方法");
                    while (count > 0){
                        count--;
                        System.out.println(Thread.currentThread().getName()+"运行结果为:"+count);
                    }
                }
            });
        }
    }
}

运行结果如下:

pool-1-thread-2进入run方法
pool-1-thread-3进入run方法
pool-1-thread-1进入run方法
pool-1-thread-1运行结果为:4
pool-1-thread-1运行结果为:3
pool-1-thread-1运行结果为:2
pool-1-thread-1运行结果为:1
pool-1-thread-1运行结果为:0
pool-1-thread-3运行结果为:4
pool-1-thread-2运行结果为:4
pool-1-thread-3运行结果为:3
pool-1-thread-2运行结果为:3
pool-1-thread-2运行结果为:2
pool-1-thread-2运行结果为:1
pool-1-thread-3运行结果为:2
pool-1-thread-3运行结果为:1
pool-1-thread-2运行结果为:0
pool-1-thread-3运行结果为:0

通过上面的结果可以看到各个线程不是按照顺序去执行。如果希望各个线程按照顺序去执行需要采用锁去实现线程的顺序执行

public class ThreadTest {
//    private static int count = 5;
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        ExecutorService executorService = new ThreadPoolExecutor(
                5,5,10,
                TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5));
        for(int i=0;i<3;i++){
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    lock.lock();
                    System.out.println("加锁成功");
                    try {
                        int count = 5;
                        System.out.println(Thread.currentThread().getName()+"进入run方法");
                        while (count > 0){
                            count--;
                            System.out.println(Thread.currentThread().getName()+"运行结果为:"+count);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        lock.unlock();
                        System.out.println("释放锁成功");
                    }
                }
            });
        }
    }
}

加锁成功
pool-1-thread-1进入run方法
pool-1-thread-1运行结果为:4
pool-1-thread-1运行结果为:3
pool-1-thread-1运行结果为:2
pool-1-thread-1运行结果为:1
pool-1-thread-1运行结果为:0
释放锁成功
加锁成功
pool-1-thread-2进入run方法
pool-1-thread-2运行结果为:4
pool-1-thread-2运行结果为:3
pool-1-thread-2运行结果为:2
pool-1-thread-2运行结果为:1
pool-1-thread-2运行结果为:0
释放锁成功
加锁成功
pool-1-thread-3进入run方法
pool-1-thread-3运行结果为:4
pool-1-thread-3运行结果为:3
pool-1-thread-3运行结果为:2
pool-1-thread-3运行结果为:1
pool-1-thread-3运行结果为:0
释放锁成功

(2)共享变量的情况(例如在实现销售场景时,如果有多个线程同时访问,必须一个销售员卖完一个货品之后,其他的销售员才可以继续在剩余物品上减一操作,也就是按顺序去减一操作)

public class ThreadTest {
    private static  volatile int count = 5;
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        ExecutorService executorService = new ThreadPoolExecutor(
                5,5,10,
                TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5));
        for(int i=0;i<5;i++){
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    lock.lock();
                    System.out.println("加锁成功");
                    try {
                        //int count = 5;
                        System.out.println(Thread.currentThread().getName()+"进入run方法");
                        if (count > 0){
                            count--;
                            System.out.println(Thread.currentThread().getName()+"运行结果为:"+count);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        lock.unlock();
                        System.out.println("释放锁成功");
                    }
                }
            });
        }
    }
}

运行结果如下(

由于count--,并非为原子操作,所以使用volatile使count对于其他线程可见,使用lock锁是为了使线程顺序执行,确保结果不会出现错误,

在jvm虚拟机中操作分为以下三步:

(1)取得原有count的值

(2)计算count-1

(3)赋值给count

):

加锁成功
pool-1-thread-1进入run方法
pool-1-thread-1运行结果为:4
释放锁成功
加锁成功
pool-1-thread-2进入run方法
pool-1-thread-2运行结果为:3
释放锁成功
加锁成功
pool-1-thread-3进入run方法
pool-1-thread-3运行结果为:2
释放锁成功
加锁成功
pool-1-thread-4进入run方法
pool-1-thread-4运行结果为:1
释放锁成功
加锁成功
pool-1-thread-5进入run方法
pool-1-thread-5运行结果为:0
释放锁成功

猜你喜欢

转载自blog.csdn.net/weixin_42163781/article/details/105067988