先写一个demo的例子
package wg.fnd.test;
/**
* @author xupf@wangreat.com
* @create 2019-03-14 10:56
*/
public class Demo {
int i = 0;
public void incr(){
i++;
}
public static void main(String[] args) {
Demo demo = new Demo();
for (int j = 0;j<2;j++) {
new Thread(() -> { // 创建两个线程
for (int k=0;k<10000;k++) { // 每个线程跑10000次
demo.incr();
}
}
).start();
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(demo.i);
}
}
这个例子中执行的结果可能是20000,或者小于20000的值,因为变量i在这是不具备原子性的,加上线程执行顺序的问题,所以出现这样的结果。
改变上边的例子,用jdk的Atomic来创建一个变量
package wg.fnd.test;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author xupf@wangreat.com
* @create 2019-03-14 10:56
*/
public class AtomicDemo {
// int i = 0;
AtomicInteger i = new AtomicInteger(0);
public void incr(){
// i++;
i.incrementAndGet();
}
public static void main(String[] args) {
AtomicDemo demo = new AtomicDemo();
for (int j = 0;j<2;j++) {
new Thread(() -> { // 创建两个线程
for (int k=0;k<10000;k++) { // 每个线程跑10000次
demo.incr();
}
}
).start();
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(demo.i);
}
}
这个例子中执行的结果一定为20000
用加锁的方式改变demo
package wg.fnd.test;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author xupf@wangreat.com
* @create 2019-03-14 10:56
*/
public class LockDemo {
int i = 0;
Lock lock = new ReentrantLock();
public void incr(){
lock.lock();
try {
i++;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
LockDemo demo = new LockDemo();
for (int j = 0;j<2;j++) {
new Thread(() -> { // 创建两个线程
for (int k=0;k<10000;k++) { // 每个线程跑10000次
demo.incr();
}
}
).start();
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(demo.i);
}
}
这个例子的执行结果一定为20000
我们来自己创建一个锁,实现jdk中的Lock
package wg.fnd.test;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
/**
* @author xupf@wangreat.com
* @create 2019-03-14 11:44
*/
public class MyLock implements Lock {
AtomicReference<Thread> owner = new AtomicReference<>(); // atomic类具有原子性
public LinkedBlockingDeque<Thread> waiter = new LinkedBlockingDeque<>(); // 等待列表
@Override
public void lock() {
// 多线程,有可能成功,也有可能失败,(一直抢)不能只抢一次
// 进行比较和交换
while (!owner.compareAndSet(null, Thread.currentThread())) {
waiter.add(Thread.currentThread()); // 抢不到就等,把当前线程放入等待列表
LockSupport.park(); // 让线程等待
//
waiter.remove(Thread.currentThread()); // 如果能执行到这里,说明唤醒了线程,那么久移除当前线程
}
}
@Override
public void unlock() {
// 判断是否有线程,如果有就释放,没有就不管
if (owner.compareAndSet(Thread.currentThread(), null)) {
// 通知那些等待列表的线程,唤醒
Object[] objects = waiter.toArray(); //数组化
for (Object object : objects) { // 遍历,拿出所有等待的线程
Thread next = (Thread) object;
LockSupport.unpark(next); // 唤醒线程
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
}