返回 登录
0

Java多线程共享资源

多线程中的一个核心问题就是对共享资源的读写问题。你永远都不知道一个线程何时在运行。如果同时有多个线程对一个对象进行读写,结果就会出现脏数据

接下来展示一个多线程同时对一个对象进行读写出现脏数据的案例。

为了方便解耦,创建一个抽象类。

public abstract class Ingenerator  {

    private volatile boolean caceled = false;
    public abstract int next();

    public void cacel(){
        caceled = true;
    }
    public boolean isCanceled(){
        return caceled;
    }

}

EvenChecker任务总是读取和测试从其相关的Ingenerator 返回的值。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EvenChecker implements Runnable {

    private Ingenerator generator;
    public EvenChecker(Ingenerator g){
        generator = g;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(!generator.isCanceled()){
            int val = generator.next();
            if(val%2!=0){
                System.out.println(val + " not even!");
                generator.cacel();
            }
        }

    }

    public static void test(Ingenerator gp,int count){
        System.out.println("Press Control to exit");
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i = 0;i<count;i++){
            exec.execute(new EvenChecker(gp));
        }
        exec.shutdown();
    }

}

继承Ingenerator抽象类的next()产生偶数。

public class EvenGenerator extends Ingenerator {
    private int currentEvenValue = 0;

    @Override
    public int next() {
        ++currentEvenValue;
        ++currentEvenValue;
        return currentEvenValue;
    }

    public static void main(String[] args) {
        EvenChecker.test(new EvenGenerator(), 10);
    }

}

一个线程有可能在另一个线程执行第一个++currentEvenValuede 操作之后,还没有来得及执行第二个操作之前调用了next()方法。这个时候可能就会产生一个奇数。也就是脏数据。

基本上所有的并发模式在解决线程冲突问题的时候,都是采用序列化访问共享资源的方案。

一个屋子只有一个浴室,多个人(多个线程)都希望能单独使用这个浴室(共享资源)。为了使用浴室,一个人先敲门,看看有没有人,如果没人的话,他就进入浴室并锁上门。等待使用浴室的人们挤在浴室门口,当锁住浴室门的那个人打开锁离开的时候,离门最近的那个人可能进入浴室,可以通过yield()和setPriority()来给线程调度器提供建议,虽然未必有用。还是取决于CPU。

Java提供关键字synchronized的形式,来防止资源冲突。当线程执行被synchronized关键字保护的代码片段时,它将检查锁是否可用,然后获取锁,执行代码,释放锁。

图片描述

学习Java的同学注意了!!!
学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:492139965 我们一起学Java!

评论