[Java基础]多线程高级2--多线程控制类

本文深入探讨Java多线程的控制机制,讲解ThreadLocal提供线程局部变量的原理及应用,分析原子类如AtomicInteger如何解决非原子性操作问题,详解基于CAS的原子操作,讨论ABA问题及其解决方案AtomicStampedReference,以及Lock类中的ReentrantLock和ReadWriteLock的使用。
摘要由CSDN通过智能技术生成

为了保证多线程的三个特性,Java引入了很多线程控制机制,这里主要介绍几种

机制 作用
ThreadLocal 线程本地变量,提供局部变量为每个线程保存一份副本
原子类 保证变量的原子性
lock类 保证线程有序性
Volatile 保证线程变量可见性

一.ThreadLocal

1.1作用

提供线程局部变量,为使用相同变量的每一个线程维护一个该变量的副本。使用的场景是:当某些数据是以线程为作用域并且不同线程有不同数据副本的时候,可以采用ThreadLocal,

1.2 常用方法

方法 作用
initValue() 副本创建的方法
get() 获取副本的方法
set() 设置副本的方法

1.3示例:两个线程转账

public class ThreadLocalDemo {
   
	//银行对象,有钱,有存款和取款两个操作
	static class Bank{
   
		ThreadLocal<Float> threadLocal = new ThreadLocal<Float>() {
   
			protected Float initialValue() {
   
				return 0.0f;
			}
			
		};
		//存款
		public Float get() {
   
			return threadLocal.get();
		}
		//取款
		public void set(Float money) {
   
			threadLocal.set(threadLocal.get()+money);
		}
	}
	
	
	//转账对象,从银行中取钱然后转账,然后保存到账户
	static class Transfer implements Runnable{
   
		private Bank bank;
		public Transfer(Bank bank){
   
			this.bank = bank;
		}
		
		@Override
		public void run() {
   
			// TODO Auto-generated method stub
			for(int i = 0;i<10;i++) {
   
				bank.set(10.0f);
				System.out.println(Thread.currentThread().getName()+"账户余额"+bank.get());
			}
		}
	}
}

在main中模拟转账

		Bank bank = new Bank();
		Transfer transfer = new Transfer(bank);
		Thread t1 =new Thread(transfer,"客户1");
		Thread t2 =new Thread(transfer,"客户2");
		t1.start();
		t2.start();

执行结果:
在这里插入图片描述

1.4分析

ThreadLocal能实现为不同的线程保存变量的原理是,它内部有个Entry,保存<线程名,变量值>,不同的线程对应着不同的value,就能加以区分了

二.原子类

Java在java.util.concurrent.atomic包中提供了很多进行原子操作的类,分为以下四大类:

操作 类型
原子更新基本类型 AtomicInteger,AtomicBoolean,AtomicLong
原子更新数组类型 AtomicIntegerArray,AtomicLongArray
原子更新引用类型 AtomicReference,AtomicStampedReference
原子更新属性类型 AtomicIntegerFileUpdater,AtomicLongFileUpdater

这些类的提供目的在于为了解决基本类型的非原子性导致在多线程并发情况下引发的问题

2.1非原子性操作问题演示

例如:i++并不是原子操作,有三个操作组成

  1. tp1 = i;
  2. tp2 = tp1+1;
  3. tp1 = tp2;
    单线程下这个代码不会有问题,但在多线程下会出现问题
static private int n;
public static void main(String[] args) throws InterruptedException {
   
	int j = 0;
	while(j<100) {
   
		n=0;
		Thread t1 = new Thread(new Runnable() {
   
			
			@Override
			public void run() {
   
				// TODO Auto-generated method stub
				for(int i=0;i<1000;i++) {
   
					n++;
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {
   
			
			@Override
			public void run() {
   
				// TODO Auto-generated method stub
				for(int i=0;i<1000;i++) {
   
					n++;
				}
			}
		});
		t1.start();
		t2
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值