Java之Thread安全实现以及注意

高并发,多线程开发的时候如何保证安全和程序的准确性?

初识Java内存模型与多线程

 

 

 什么是不安全

当多个线程同时操作一个数据结构的时候产生了相互修改和串行的情况,没有保证数据的一致性,我们通常称这种设计的代码为“线程不安全的”。

有这么一个场景,假设5个用户,都来给一个数字加1的工作,那么最后应该是得到加5的结果:看一下下面的事例。

单个用户干活类:Count.

 

public class Count {
public int num=0;

public void add() {
    try {
        Thread.sleep(51);
    }catch(InterruptedException e) {
        
    }
    num+=1;
    System.out.println(Thread.currentThread().getName()+"-"+num);
}
}
用户类,干Count的活。

public class ThreadA_1 extends Thread {
private Count count;
public ThreadA_1(Count count) {
    this.count=count;
}
    @Override
    public void run() {
        // TODO Auto-generated method stub
        count.add();
    }

}
5个人干完活,最后的值


public class TestA_1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
Count count=new Count();
for(int i=0;i<5;i++) {
    ThreadA_1 task=new ThreadA_1(count);
    task.start();
}
try {
    Thread.sleep(1001);
}catch(InterruptedException e) {
    e.printStackTrace();
}
System.out.println("5个人干完活:最后的值是"+count.num);
    }

}
运行结果,值可能是1,2,3,4,5中的任意一个

什么是安全

我们把上一节的例子单个用户干活类Count做如下修改,添加synchronized关键字。

 

public class Count {
public int num=0;

public synchronized void add() {
    try {
        Thread.sleep(51);
    }catch(InterruptedException e) {
        
    }
    num+=1;
    System.out.println(Thread.currentThread().getName()+"-"+num);
}
}
运行结果如下:

 

隐式锁,又称线程同步synchronized

 

 

 

 

 

 

 

 

 

显示锁Lock和ReentrantLock

 

 

 

 

 

 

 

 

 

 

 

 

显示锁ReadWriteLock和ReentrantReadWriteLock

 

 

 

 

 

 

实例体会:

第一种情况,先体验一下ReadLock和WriteLock单独使用的情况。

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Test_2 {
public static void main(String[] args) {
    final Count1 ct=new Count1();
    for(int i=0;i<2;i++) {
        new Thread() {
            public void run() {
                ct.get();
            }
        }.start();
    }
    for(int i=0;i<2;i++) {
        new Thread() {
            public void run() {
                ct.put();
            }
        }.start();
    }
}
}
class Count1{
    private final ReentrantReadWriteLock rw1=new ReentrantReadWriteLock();
    public void get() {
        rw1.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"read start.");
            Thread.sleep(1000L);
            System.out.println(Thread.currentThread().getName()+"read end.");
            
        }catch(InterruptedException e) {
            e.printStackTrace();
        }finally{
            rw1.readLock().unlock();
        }
    }
    public void put() {
        rw1.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"write start.");
            Thread.sleep(1000L);
            System.out.println(Thread.currentThread().getName()+"write end.");
            
        }catch(InterruptedException e) {
            e.printStackTrace();
        }finally{
            rw1.writeLock().unlock();
        }
    }
}
运行结果:

 第二种情况,我们体会一个ReadLock和WriteLock的复杂使用情况,模拟一个有读写数据的场景,仔细体会一下

 显示锁StampedLock

 

 

 

 

 

 

 

 

 

什么是死锁

 

 

 

 

Java关键字volatile修饰变量

 

 

原子操作atomic

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值