线程学习 (四) 线程安全和线程锁机制

线程安全:当程序多个并发线程同时访问一个目标或者资源时,对其最终所产生结果的正确性不会造成影响的情况下,就是所说的线程安全。

线程不安全:多个线程同时访问一个目标或资源的时候,随着线程的访问进行,在某种情况下会造成最终结果的改变,这就是所说的线程不安全

实现和预防线程安全的方法:

1.减少多线程访问对象的全局变量的引用

对全局变量进行操作的方法在多线程访问的情况下会造成结果的更改不能及时的得到验证和反馈,最终造成预期结果的改变 ,如下:

启动1000个线程对含有全局变量的方法进行并发访问:

import javax.jws.WebParam;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadPoolExecutorTest {

public static void main(String[] args) {


    ThreadPoolExecutor executor = new ThreadPoolExecutor(5,//核心线程数量
            1000,//最大线程数量限制
            3,//空闲等待时间(非核心线程到达时间还处于空闲状态将被回收)
            TimeUnit.SECONDS,//keepAliveTime 量化单位
            new ArrayBlockingQueue<Runnable>(2));//等待线程队列

             ModelClass modelClass=new ModelClass();

    for (int i = 0; i < 1000; i++) {
        executor.execute(new ThreadTest(modelClass));
    }

    executor.shutdown();

}

//线程类
static class ThreadTest implements Runnable {

//引用方法所在类
ModelClass modelClass;

    public ThreadTest(ModelClass modelClass) {
        this.modelClass = modelClass;
    }

    @Override
    public void run() {

        modelClass.getCount();

    }
}

static class ModelClass {

    public int x =1000;//全局变量


    public  void getCount() {

        System.out.println(--x);

    }

}

}

结果:

这里写图片描述

注意:在多线程并发访问中,随着并发线程总量的不断增加,线程的安全性是逐步下降的

2.使用关键字 synchronized

线程的锁机制原理为,相同的目标和方法在添加synchronized关键字后,只允许同一时间的单个线程进行拥有访问执行,在当前线程执行完之后才会解锁供后面的线程使用,也就是说在多线程访问的时候在synchronized 处线程形成等待队列,而不是根据cpu分配资源进行自由的访问执行

代码:

在方法声明部分加上synchronized

static class ModelClass {

    public int x =1000;
    public synchronized void getCount() {//添加锁机制,只允许单线程同步执行,后来线程等待
        System.out.println(--x);

    }

}

结果:

这里写图片描述

上面这种形式在方法内容相对简单时使用还可以,当方法体内容丰富,执行效率会很低,所以可以在方法体中进行部分内容锁定 如下:

static class ModelClass {

    public int x =1000;


    public  void getCount() {

        synchronized(this){//方法体部分锁定

            System.out.println(--x);
        }
    }
}

3.使用Lock

static class ModelClass {

    public int x =1000;

    Lock lock=new ReentrantLock();

    public  void getCount() {
        lock.lock();//锁定
        System.out.println(--x);
        lock.unlock();//解锁
    }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值