public class Synchronizedtest implements Runnable {
int i = 10; //共享变量
@Override
public void run() {
if( i == 10 ){
System.out.println("i == 10");
sys
i++;
}
}
public static void main(String[] args) throws InterruptedException {
Synchronizedtest st = new Synchronizedtest();
Thread t1 = new Thread(st,"线程1");
Thread t2 = new Thread(st,"线程2");
t1.start();
// t1.sleep(1000); 第一次测试先注释掉,第二次测试打开,下面为两次测试结果
t2.start();
}
}
i == 10
i == 10
i == 10
问题分析:
暂停
” 1秒,t2线程还不开启,t1在1秒内绝对执行完之后才开启t2线程,这样 i 的值已经更新为11了,此时t2就不输出内容public class Synchronizedtest implements Runnable {
//使用的是该类的锁
@Override
public synchronized void run() {
for(int i = 0;i < 100;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
public static void main(String[] args) {
Synchronizedtest st = new Synchronizedtest();
Thread t1 = new Thread(st,"线程1");
Thread t2 = new Thread(st,"线程2");
t1.start();
t2.start();
}
}
线程1------96
线程1------97
线程1------98
线程1------99 //获得锁,执行完才释放,t2线程不能执行该方法
线程2------0
线程2------1
线程2------2
线程2------3
线程2------4
public void run() {
//使用的也是该类的锁,打印结果是一致的
//也可以用一个对象作为锁,客户端锁,但不推荐
synchronized(this){
for(int i = 0;i < 100;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
}
public class test {
//静态方法属于类,获取到的锁是属于类锁(类的字节码文件对象)
public static synchronized void test() {
}
}
二者不会冲突,即即可获得对象锁,也可获得类锁
public class testLock {
//对象锁
public synchronized void lockOne() throws InterruptedException {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
//类锁
public static synchronized void lockTwo() throws InterruptedException {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
public static void main(String[] args) {
testLock demo = new testLock();
Thread t1 = new Thread(() -> {
try {
demo.lockOne();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
lockTwo();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
//两个线程都执行
Thread-1: 99
Thread-0: 35
public class Widget {
// 锁住了
public synchronized void doSomething() {
System.out.println("Wigget--------------");
}
}
public class LoggingWidget extends Widget {
// 锁住了
public synchronized void doSomething() {
System.out.println("LoggingWidget------------");
super.doSomething();
}
}
在JUC并发包下有locks接口,里面有三个抽象类
其中,AbstractQueuedSynchronizer为AQS,而且我们后面要讲的Lock显式锁的内部类(ReentrantLock、 ReadWriteLock)都是他的子类,根据名字可以知道他是抽象队列同步器,AQS是ReentrantReadWriteLock和ReentrantLock的基础,因为默认的实现都是在内部类Syn中,而Syn继承了AQS
根据其注释可知:
volatile保证状态可见性
/**
* The synchronization state.
*/
private volatile int state;
CAS算法保证原子性
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
acquire(int)尝试获取资源,如果获取失败,将线程插入等待队列。插入等待队列后,acquire(int)并没有放弃获取资源,而是根据前置节点状态状态判断是否应该继续获取资源,如果前置节点是头结点,继续尝试获取资源,如果前置节点是SIGNAL状态,就中断当前线程,否则继续尝试获取资源。直到当前线程被park()或者获取到资源,acquire(int)结束。
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//子类实现的类,模板模式
首先调用子类的tryRelease()方法释放锁,然后唤醒后继节点,在唤醒的过程中,需要判断后继节点是否满足情况,如果后继节点不为且不是作废状态,则唤醒这个后继节点,否则从tail节点向前寻找合适的节点,如果找到,则唤醒
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
构造方法
public ReentrantLock() {
sync = new NonfairSync();
}
//默认非公平锁
//也支持公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
lock方法
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1)) //CAS保证
setExclusiveOwnerThread(Thread.currentThread()); //尝试获取锁
else
acquire(1); //失败就调用AQS的acquire方法
}
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { //如果锁是空闲的
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}else if (current == getExclusiveOwnerThread()) { //重入锁
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
unlock
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) { //子类实现
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //计数器减 1
if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { //莫得锁了
free = true;
setExclusiveOwnerThread(null); //锁线程设置为空
}
setState(c);
return free;
}
ReentrantReadWriteLock读写锁:
读写锁有个接口:ReadWriteLock,定义了两个方法:readLcok(),writeLock(),而ReentrantReadWriteLock实现了该接口
获取写锁
protected final boolean tryAcquire(int acquires) {
/*
* Walkthrough:
* 1. If read count nonzero or write count nonzero
* and owner is a different thread, fail.
* 2. If count would saturate, fail. (This can only
* happen if count is already nonzero.)
* 3. Otherwise, this thread is eligible for lock if
* it is either a reentrant acquire or
* queue policy allows it. If so, update state
* and set owner.
*/
Thread current = Thread.currentThread();
int c = getState(); //状态
int w = exclusiveCount(c);
if (c != 0) {
// (Note: if c != 0 and w == 0 then shared count != 0)
if (w == 0 || current != getExclusiveOwnerThread()) //不是当前线程
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT) //大于饱和
throw new Error("Maximum lock count exceeded");
// Reentrant acquire
setState(c + acquires);
return true;
}
if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
获取读锁
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) //存在写锁,但不在本线程
return -1;
int r = sharedCount(c);
if (!readerShouldBlock() && r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)){
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
}else if (firstReader == current) {
firstReaderHoldCount++;
}else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return 1;
}
return fullTryAcquireShared(current);
}
public class Counter {
private final Lock lock = new ReentrantLock();
private int count;
public void add(int n) {
lock.lock();
try {
count += n;
} finally {
lock.unlock();
}
}
}
public class Counter {
private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
private final Lock rlock = rwlock.readLock(); //获取读锁
private final Lock wlock = rwlock.writeLock(); //获取写锁
private int[] counts = new int[10];
public void inc(int index) {
wlock.lock(); // 加写锁
try {
counts[index] += 1;
} finally {
wlock.unlock(); // 释放写锁
}
}
public int[] get() {
rlock.lock(); // 加读锁
try {
return Arrays.copyOf(counts, counts.length);
} finally {
rlock.unlock(); // 释放读锁
}
}
}
class conditionTest {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition(); //一定要这样获取绑定条件
public void test1() {
lock.lock();
try {
//dosomenthing
condition.signalAll();
} finally {
lock.unlock();
}
}
public void test2() {
lock.lock();
try {
//dosomething
condition.await();
} finally {
lock.unlock();
}
}
}