多线程的线程安全问题

在多线程的使用中往往需要多个线程对一个共享数据进行操作,这时就会出现线程安全问题,得到的数据可能会重复,错误,那么可以使用以下的三种方法解决:

同步代码块Synchronized

将你操作共享数据的代码放入Synchronized(){}中

继承Thread

代码:

class MyThreadSynchronized extends Thread{
    //共享数据
    private static int count=100;
    @Override
    public void run() {
        while (true){
            synchronized (MyThreadSynchronized.class){
                if(count>0){
                    System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
                    count--;
                }else{
                    break;
                }
            }
        }
    }
}
public class ThreadExtendsSynchronized {


    public static void main(String[] args) {
        MyThreadSynchronized myThreadSynchronized1=new MyThreadSynchronized();
        MyThreadSynchronized myThreadSynchronized2=new MyThreadSynchronized();

        myThreadSynchronized1.setName("线程一");
        myThreadSynchronized2.setName("线程二");

        myThreadSynchronized1.start();
        myThreadSynchronized2.start();
    }
}

在继承Thread创建多线程中,需要将共享数据设置为静态(唯一),同时Synchronized的同步监视器不能写成this,因为在main中创建了多个“MyThreadSynchronized”的对象,因此写成" 此类名.class"。

实现Runnable
代码:

class MyRunnableSynchronized implements Runnable{

    private int count=100;

    public void run() {
        while(true){
            synchronized (this) {
                if(count>0){
                    System.out.println(Thread.currentThread().getName() + ":第" + count +"个");
                    count--;
                }else{
                    break;
                }
            }
        }
    }
}
public class ThreadRunnableSynchronized {
    public static void main(String[] args) {
        MyRunnableSynchronized myRunnableSynchronized = new MyRunnableSynchronized();

        Thread thread1 = new Thread(myRunnableSynchronized);
        Thread thread2 = new Thread(myRunnableSynchronized);

        thread1.setName("线程一");
        thread2.setName("线程二");

        thread1.start();
        thread2.start();
    }
}

在实现Runnable创建多线程中则没有继承中的那些问题,在main中只需创建一个类对象,同步监视器也只需用this就行。

同步方法

将操作共享数据的代码放入同步方法中

继承Thread
代码

class MyThreadExtends2 extends Thread{

    private static int count=100;
    @Override
    public void run() {
        while (true){
               a();
               if(count<=0){
                   break;
               }
        }
    }
    //用static保证每一个此类的对象都使用这个方法
    public static synchronized void a(){
            if(count>0){
                System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
                count--;
            }
    }
}
public class ThreadExtendsSynchronized2 {
    public static void main(String[] args) {
        MyThreadExtends2 myThreadExtends21=new MyThreadExtends2();
        MyThreadExtends2 myThreadExtends22=new MyThreadExtends2();

        myThreadExtends21.setName("线程一");
        myThreadExtends22.setName("线程二");

        myThreadExtends21.start();
        myThreadExtends22.start();
    }
}

同样的在继承中也需要将共享数据定义为静态

实现Runnable创建多线程
代码:

class MyThreadRunnable2 implements Runnable{
    private int count=100;
    public void run() {
        while(true){
            a();
            if(count<=0){
                break;
            }
        }
    }
    public synchronized void a(){
        if(count>0){
            System.out.println(Thread.currentThread().getName() + ":第" + count +"个");
            count--;
        }
    }
}
public class ThreadRunnableSynchronized2 {
    public static void main(String[] args) {
        MyThreadRunnable2 myThreadRunnable2=new MyThreadRunnable2();
        Thread thread1=new Thread(myThreadRunnable2);
        Thread thread2=new Thread(myThreadRunnable2);
        thread1.setName("线程一");
        thread2.setName("线程二");
        thread1.start();
        thread2.start();

    }
}

使用ReentrantLock

实现Runnable创建多线程(继承方法差不多)
代码:

class MyThreadReentrantLock implements Runnable{

    private int count=100;
    //创建ReentrantLock的对象
    ReentrantLock lock=new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try{
            //加“锁”
                lock.lock();
                if(count>0){
                    System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
                    count--;
                }else{
                    break;
                }
            }finally {
            //解“锁”
                lock.unlock();
            }
        }
    }
}
public class ThreadRunnableLock {
    public static void main(String[] args) {
        MyThreadReentrantLock myThreadReentrantLock=new MyThreadReentrantLock();
        Thread thread1=new Thread(myThreadReentrantLock);
        Thread thread2=new Thread(myThreadReentrantLock);

        thread1.setName("线程一");
        thread2.setName("线程二");

        thread1.start();
        thread2.start();
    }
}

ReentrantLock类中的lock()和 unlock()需将代码写在try语句块中(无需添加catch语句块) finally语句块中写unlock()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值