1.同步调用会一直等到方法返回
2.异步调用会立马返回,虽然返回时事情没有做完,然后再后台开启一个新的线程做自己的事情。
3.两个进程同时执行,叫并行
4.有一个调度的过程叫并发,一会做着一会做那
5.单核cpu只有并发 没有并行,因为同一时间只能执行一个线程
6.临界区,同一时间一次只能有一个线程调用,对于其他进程来说就是阻塞状态,如果有多个线程一起操作,那就是非阻塞状态
活锁:
饥饿:优先权低,一直得不到资源。
并发级别:
阻塞调度:
阻塞
非阻塞调度:
无障碍--操作数据时发现和别进程操作同一条数据,他自己会回滚,重新操作数据
无锁--无障碍,保证至少有一个线程是可以退出临界区的,而不会全部阵亡掉在临界区
无等待--无锁,无饥饿,要求所有的线程都必须在有限步完成。
每一个线程都是Runable的实现
1. 无锁类的原理详解
1.1.CAS
CAS算法的过程是这样:它包含3个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。仅当V
值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么
都不做。最后,CAS返回当前V的真实值。CAS操作是抱着乐观的态度进行的,它总是认为自己可以成功完成
操作。当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程
不会被挂起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。基于这样的原理,CAS
操作即时没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。
2. 无锁类的使用
AtomicInteger
public final int get() //取得当前值
public final void set(int newValue) //设置当前值
public final int getAndSet(int newValue) //设置新值,并返回旧值3
public final boolean compareAndSet(int expect, int u)
//如果当前值为expect,则设置为u
public final int getAndIncrement() //当前值加1,返回旧值
public final int getAndDecrement() //当前值减1,返回旧值
public final int getAndAdd(int delta) //当前值增加delta,返回旧值
public final int incrementAndGet() //当前值加1,返回新值
public final int decrementAndGet() //当前值减1,返回新值
public final int addAndGet(int delta) //当前值增加delta,返回新值
AtomicReference
get()
set(V)
compareAndSet()
getAndSet(V)
AtomicStampedReference
ABA问题
//比较设置 参数依次为:期望值 写入新值 期望时间戳 新时间戳
public boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp)
//获得当前对象引用
public V getReference()
//获得当前时间戳
public int getStamp()
//设置当前对象引用和时间戳
public void set(V newReference, int newStamp)
AtomicIntegerArray AtomicLongArray AtomicReferenceArray
//获得数组第i个下标的元素
public final int get(int i)
//获得数组的长度
public final int length()
//将数组第i个下标设置为newValue,并返回旧的值
public final int getAndSet(int i, int newValue)
//进行CAS操作,如果第i个下标的元素等于expect,则设置为update,设置成功返回true
public final boolean compareAndSet(int i, int expect, int update)
//将第i个下标的元素加1
public final int getAndIncrement(int i)
//将第i个下标的元素减1
public final int getAndDecrement(int i)
//将第i个下标的元素增加delta(delta可以是负数)
public final int getAndAdd(int i, int delta)
AtomicIntegerFieldUpdater AtomicLongFieldUpdater AtomicReferenceFieldUpdater
AtomicIntegerFieldUpdater.newUpdater()
incrementAndGet()
public class AtomicIntegerFieldUpdaterDemo {
public static class Candidate{
int id;
volatile int score;
}
public final static AtomicIntegerFieldUpdater<Candidate> scoreUpdater=AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");
//检查Updater是否工作正确,通过反射获取对象,里面是字段的名称
public static AtomicInteger allScore=new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
final Candidate stu=new Candidate();
Thread[]t=new Thread[10000];
for(int i = 0; i < 10000 ; i++) {
t[i]=new Thread() {
public void run() {
if(Math.random()>0.4){
scoreUpdater.incrementAndGet(stu);
allScore.incrementAndGet();
}
}
};
t[i].start();
}
for(int i = 0; i < 10000 ; i++) {
t[i].join();
}
System.out.println("score="+stu.score);
System.out.println("allScore="+allScore);
}
}
小说明
1.Updater只能修改它可见范围内的变量。因为Updater使用反射得到这个变量。如果变量不可见,就会出错。
比如如果score申明为private,就是不可行的。
2.为了确保变量被正确的读取,它必须是volatile类型的。如果我们原有代码中未申明这个类型,那么简单得
申明一下就行,这不会引起什么问题。6
3. 由于CAS操作会通过对象实例中的偏移量直接进行赋值,因此,它不支持static字段(Unsafe.
objectFieldOffset()不支持静态变量)。
2.异步调用会立马返回,虽然返回时事情没有做完,然后再后台开启一个新的线程做自己的事情。
3.两个进程同时执行,叫并行
4.有一个调度的过程叫并发,一会做着一会做那
5.单核cpu只有并发 没有并行,因为同一时间只能执行一个线程
6.临界区,同一时间一次只能有一个线程调用,对于其他进程来说就是阻塞状态,如果有多个线程一起操作,那就是非阻塞状态
活锁:
饥饿:优先权低,一直得不到资源。
并发级别:
阻塞调度:
阻塞
非阻塞调度:
无障碍--操作数据时发现和别进程操作同一条数据,他自己会回滚,重新操作数据
无锁--无障碍,保证至少有一个线程是可以退出临界区的,而不会全部阵亡掉在临界区
无等待--无锁,无饥饿,要求所有的线程都必须在有限步完成。
每一个线程都是Runable的实现
1. 无锁类的原理详解
1.1.CAS
CAS算法的过程是这样:它包含3个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。仅当V
值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么
都不做。最后,CAS返回当前V的真实值。CAS操作是抱着乐观的态度进行的,它总是认为自己可以成功完成
操作。当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程
不会被挂起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。基于这样的原理,CAS
操作即时没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。
2. 无锁类的使用
AtomicInteger
public final int get() //取得当前值
public final void set(int newValue) //设置当前值
public final int getAndSet(int newValue) //设置新值,并返回旧值3
public final boolean compareAndSet(int expect, int u)
//如果当前值为expect,则设置为u
public final int getAndIncrement() //当前值加1,返回旧值
public final int getAndDecrement() //当前值减1,返回旧值
public final int getAndAdd(int delta) //当前值增加delta,返回旧值
public final int incrementAndGet() //当前值加1,返回新值
public final int decrementAndGet() //当前值减1,返回新值
public final int addAndGet(int delta) //当前值增加delta,返回新值
AtomicReference
get()
set(V)
compareAndSet()
getAndSet(V)
AtomicStampedReference
ABA问题
//比较设置 参数依次为:期望值 写入新值 期望时间戳 新时间戳
public boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp)
//获得当前对象引用
public V getReference()
//获得当前时间戳
public int getStamp()
//设置当前对象引用和时间戳
public void set(V newReference, int newStamp)
AtomicIntegerArray AtomicLongArray AtomicReferenceArray
//获得数组第i个下标的元素
public final int get(int i)
//获得数组的长度
public final int length()
//将数组第i个下标设置为newValue,并返回旧的值
public final int getAndSet(int i, int newValue)
//进行CAS操作,如果第i个下标的元素等于expect,则设置为update,设置成功返回true
public final boolean compareAndSet(int i, int expect, int update)
//将第i个下标的元素加1
public final int getAndIncrement(int i)
//将第i个下标的元素减1
public final int getAndDecrement(int i)
//将第i个下标的元素增加delta(delta可以是负数)
public final int getAndAdd(int i, int delta)
AtomicIntegerFieldUpdater AtomicLongFieldUpdater AtomicReferenceFieldUpdater
AtomicIntegerFieldUpdater.newUpdater()
incrementAndGet()
public class AtomicIntegerFieldUpdaterDemo {
public static class Candidate{
int id;
volatile int score;
}
public final static AtomicIntegerFieldUpdater<Candidate> scoreUpdater=AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");
//检查Updater是否工作正确,通过反射获取对象,里面是字段的名称
public static AtomicInteger allScore=new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
final Candidate stu=new Candidate();
Thread[]t=new Thread[10000];
for(int i = 0; i < 10000 ; i++) {
t[i]=new Thread() {
public void run() {
if(Math.random()>0.4){
scoreUpdater.incrementAndGet(stu);
allScore.incrementAndGet();
}
}
};
t[i].start();
}
for(int i = 0; i < 10000 ; i++) {
t[i].join();
}
System.out.println("score="+stu.score);
System.out.println("allScore="+allScore);
}
}
小说明
1.Updater只能修改它可见范围内的变量。因为Updater使用反射得到这个变量。如果变量不可见,就会出错。
比如如果score申明为private,就是不可行的。
2.为了确保变量被正确的读取,它必须是volatile类型的。如果我们原有代码中未申明这个类型,那么简单得
申明一下就行,这不会引起什么问题。6
3. 由于CAS操作会通过对象实例中的偏移量直接进行赋值,因此,它不支持static字段(Unsafe.
objectFieldOffset()不支持静态变量)。