欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程共享资源

程序员文章站 2024-02-17 17:36:22
...

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

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

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

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