Java并发程序设计(七)乐天派:无锁
无锁
一、概述
无锁是处理并发的一种乐观策略,它会假设对资源的访问是没有冲突的。既然没有冲突自然不需要等待,所以所有的线程都可以在不停顿的状态下执行。那遇到冲突怎么办?接下来请看,无锁绝招“CAS”即比较交换术。
二、CAS原理
CAS即Compare and swap.其算法过程是这样的:它有三个参数:
1.V表示要更新的变量
2.E表示期望值
3.N表示新值
仅当V等于E时,才会将V设为N。如果V和N不同,则说明有其他线程做了更新,则该线程什么都不做。当多个线程同时使用CAS进行变量操作时,只有一个会更新成功,其余都会失败。失败的线程不会被挂起,而是进行重试。
三、无锁的线程安全整数:AtomicInteger
AtomicInteger主要方法如下(对于其他无锁线程安全类,其方法类似):
public final int get() //取得当前值
public final void set(int newValue) //设置当前值
public final int getAndset(int newValue) //设置新值返回旧值
public final boolean compareAndSet(int except,int u) //如果当前值为except则设为u
public final int getAndIncrement() //当前值加1返回旧值
public final int getAndDecrement()
public final int getAndAdd(int delta)
public final int incrementAndGet()
public final int decrementAndGet()
public final int addAndGet()
就AtomicInteger核心字段:
private volatile int value; //代表AtomicInteger当前的值
private static final long valueOffset; //value字段的偏移量
AtomicInteger的使用示例:
public class AutomicIntegerDemo {
static AtomicInteger i=new AtomicInteger();
public static class addThread implements Runnable{
@Override
public void run() {
for(int j=0;j<1000;j++){
i.incrementAndGet();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread[] ts=new Thread[10];
for(int j=0;j<10;j++){
ts[j]=new Thread(new addThread());
}
for(int j=0;j<10;j++) ts[j].start();
for (int j=0;j<10;j++) ts[j].join();
System.out.println(i);
}
}
相比使用锁,使用无锁会有更好的性能。
四、CAS算法逻辑上瑕疵及解决办法:AtomicStampedReference
CAS算法逻辑上的瑕疵:当你获得对象当前数据后,在准备修改为新值前,对象的值被其他对象连续修改了两次,而经过这两次修改后,对象的值又恢复到旧值。这样,当前线程就无法判断该值是否被修改过。也就是说你修改的对象数值没有过程状态信息。
AtomicStampedReference内部不仅维护了对象值还维护了一个状态值。
五、无锁数组
当前可用的原子数组有:AtomicIntegerArray,AtomicLongArray和AtomicReferenceArray
public class AtomicIntegerArrayDemo {
static AtomicIntegerArray array=new AtomicIntegerArray(10);
public static class addThread implements Runnable{
@Override
public void run() {
for (int j=0;j<1000;j++){
array.getAndIncrement(j%array.length());
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread[] ts=new Thread[10];
for (int j=0;j<10;j++){
ts[j]=new Thread(new addThread());
}
for (int j=0;j<10;j++) ts[j].start();
for (int j=0;j<10;j++) ts[j].join();
System.out.println(array);
}
}
六、让普通变量也享受原子操作:AtomicIntegerFieldUpdater
public class AtomicIntegerFieldUpdaterDemon {
public static class Candidate{
int id;
volatile int score;
}
public final static AtomicIntegerFieldUpdater<Candidate> scoreUpdater=
AtomicIntegerFieldUpdater.newUpdater(Candidate.class,"score");
public static AtomicInteger checkScore=new AtomicInteger(0); //用于检测
public static void main(String[] args) throws InterruptedException {
final Candidate candidate=new Candidate();
Thread[] threads=new Thread[1000];
for (int i=0;i<1000;i++){
threads[i]=new Thread(){
public void run(){
if (Math.random()>0.4){
scoreUpdater.incrementAndGet(candidate);
checkScore.incrementAndGet();
}
}
};
threads[i].start();
}
for (int i=0;i<1000;i++) threads[i].join();
System.out.println("score="+candidate.score);
System.out.println("checkScore="+checkScore);
}
}
注意事项:
1.Updater只能修改可见范围内的变量。
2.变量必须是volatile
3.变量不能是static的
Java并发程序设计(七)乐天派:无锁的更多相关文章
- 【实战Java高并发程序设计 2】无锁的对象引用:AtomicReference
AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,而AtomicReference则对应普通的对象引用.也就是它可以保证你在修 ...
- Java并发程序设计(十三)锁的性能优化
锁的性能优化 一.优化注意事件 一)减少锁的持有时间 只在必要时进行同步,能明显减少锁的持有时间. 二)锁的细化 缺陷:当系统需要全局锁时,其消耗的资源会比较多. 三)锁的分离 比如读写分离锁 四)锁 ...
- Java并发基础:了解无锁CAS就从源码分析
https://segmentfault.com/a/1190000015881923
- Java并发程序设计(一) 基础概念
Java并发程序设计(一) 基础概念 一.必须知道的几个概念 一)同步(Synchronous)和异步(Asynchronous) 同步:同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后 ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- java并发笔记之synchronized 偏向锁 轻量级锁 重量级锁证明
警告⚠️:本文耗时很长,先做好心理准备 本篇将从hotspot源码(64 bits)入手,通过分析java对象头引申出锁的状态:本文采用大量实例及分析,请耐心看完,谢谢 先来看一下hotspot的 ...
- Java并发编程:synchronized和锁优化
1. 使用方法 synchronized 是 java 中最常用的保证线程安全的方式,synchronized 的作用主要有三方面: 确保线程互斥的访问代码块,同一时刻只有一个方法可以进入到临界区 保 ...
- java并发笔记之证明 synchronized锁 是否真实存在
警告⚠️:本文耗时很长,先做好心理准备 证明:偏向锁.轻量级锁.重量级锁真实存在 由[java并发笔记之java线程模型]链接: https://www.cnblogs.com/yuhangwang/ ...
- 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...
随机推荐
- malloc 函数详解【转】
转自:https://www.cnblogs.com/Commence/p/5785912.html 很多学过C的人对malloc都不是很了解,知道使用malloc要加头文件,知道malloc是分配一 ...
- quartz在application中的使用
项目结构图: TestMain.java package com; import org.quartz.Scheduler; import org.quartz.impl.StdSchedulerFa ...
- PYTHON-函数的定义与调用,返回值,和参数
函数基础'''1. 什么是函数 具备某一功能的工具->函数 事先准备工具的过程--->函数的定义 遇到应用场景,拿来就用---->函数的调用 函数分类两大类: 1. 内置函数 2. ...
- python3 + selenium 之元素定位
8种定位方式 定位一个元素 webdriver提供了一系列的对象定位方法,常用的有以下几种 driver.find_element_by_name()--最常用,简单 driver.find_elem ...
- python 全栈开发,Day120(路由系统, 实例化Flask的参数, 蓝图(BluePrint), before_request after_request)
昨日内容回顾 1.Flask: from flask import Flask app = Flask(__name__) # 从源码中可以看出,Flask集成的run方法是由werkzeug中的ru ...
- jdk提供的数组扩容方法:System.arraycopy
package chapter7; /* * jdk提供的扩容方法 * System.arraycopy */public class TestArrayjdk { public static voi ...
- webpack 使用环境变量
要在开发和生产构建之间,消除 webpack.config.js 的差异.你可能需要环境变量. 可以使用 Node.js 模块的标准方式:在运行 webpack 时设置环境变量,并且使用 Node.j ...
- python爬取百度贴吧帖子
最近偶尔学下爬虫,放上第二个demo吧 #-*- coding: utf-8 -*- import urllib import urllib2 import re #处理页面标签类 class Too ...
- HTML&CSS学习笔记
<table> <thead> <tr> // table row <th></th> // table head & ...
- 64位JDK+tomcat6+myeclipse 10安装与配置
一.安装JDK与配置环境与检验配置成功: 1.进入java.com网站,然后按照以下步骤进行 =>=>=>=>=> =>=>等会出现java茶杯双击,一次一 ...