From 62010aba729e30227b489996b08de21ddd964565 Mon Sep 17 00:00:00 2001 From: xycodec Date: Wed, 6 Nov 2019 21:50:31 +0800 Subject: [PATCH 1/4] MultiThreadPro --- .gitignore | 1 + .idea/.gitignore | 2 + .idea/MultiThreadPro.iml | 19 ++ .idea/compiler.xml | 16 ++ .idea/dictionaries/xycode.xml | 7 + .../Maven__com_beust_jcommander_1_72.xml | 13 ++ .idea/libraries/Maven__junit_junit_4_12.xml | 13 ++ ..._org_apache_extras_beanshell_bsh_2_0b6.xml | 13 ++ .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 ++ .../Maven__org_testng_testng_6_14_3.xml | 13 ++ .idea/misc.xml | 13 ++ .idea/modules.xml | 8 + .idea/vcs.xml | 6 + MultiThreadDP.iml | 11 ++ pom.xml | 41 +++++ src/com/xycode/aqsLock/MyLock.java | 165 ++++++++++++++++++ .../CountDownLatchDemo2.java | 68 ++++++++ .../cyclicBarrierDemo/CyclicBarrierDemo1.java | 57 ++++++ src/com/xycode/exchanger/ExchangerDemo_1.java | 55 ++++++ src/com/xycode/observer/BinaryObserver.java | 13 ++ src/com/xycode/observer/Main.java | 18 ++ src/com/xycode/observer/Observer.java | 7 + src/com/xycode/observer/OctalObserver.java | 12 ++ src/com/xycode/observer/Subject.java | 29 +++ src/com/xycode/spinlock/MySpinLock.java | 49 ++++++ .../xycode/synchronizedDemo/LockObject.java | 95 ++++++++++ .../xycode/synchronizedDemo/LockStatic.java | 78 +++++++++ 27 files changed, 835 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/MultiThreadPro.iml create mode 100644 .idea/compiler.xml create mode 100644 .idea/dictionaries/xycode.xml create mode 100644 .idea/libraries/Maven__com_beust_jcommander_1_72.xml create mode 100644 .idea/libraries/Maven__junit_junit_4_12.xml create mode 100644 .idea/libraries/Maven__org_apache_extras_beanshell_bsh_2_0b6.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml create mode 100644 .idea/libraries/Maven__org_testng_testng_6_14_3.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 MultiThreadDP.iml create mode 100644 pom.xml create mode 100644 src/com/xycode/aqsLock/MyLock.java create mode 100644 src/com/xycode/cyclicBarrierDemo/CountDownLatchDemo2.java create mode 100644 src/com/xycode/cyclicBarrierDemo/CyclicBarrierDemo1.java create mode 100644 src/com/xycode/exchanger/ExchangerDemo_1.java create mode 100644 src/com/xycode/observer/BinaryObserver.java create mode 100644 src/com/xycode/observer/Main.java create mode 100644 src/com/xycode/observer/Observer.java create mode 100644 src/com/xycode/observer/OctalObserver.java create mode 100644 src/com/xycode/observer/Subject.java create mode 100644 src/com/xycode/spinlock/MySpinLock.java create mode 100644 src/com/xycode/synchronizedDemo/LockObject.java create mode 100644 src/com/xycode/synchronizedDemo/LockStatic.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1de5659 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..5c98b42 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/.idea/MultiThreadPro.iml b/.idea/MultiThreadPro.iml new file mode 100644 index 0000000..638dea0 --- /dev/null +++ b/.idea/MultiThreadPro.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..511b0c0 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dictionaries/xycode.xml b/.idea/dictionaries/xycode.xml new file mode 100644 index 0000000..1e05936 --- /dev/null +++ b/.idea/dictionaries/xycode.xml @@ -0,0 +1,7 @@ + + + + xycode + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_beust_jcommander_1_72.xml b/.idea/libraries/Maven__com_beust_jcommander_1_72.xml new file mode 100644 index 0000000..ad12dd9 --- /dev/null +++ b/.idea/libraries/Maven__com_beust_jcommander_1_72.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__junit_junit_4_12.xml b/.idea/libraries/Maven__junit_junit_4_12.xml new file mode 100644 index 0000000..d411041 --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_4_12.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_extras_beanshell_bsh_2_0b6.xml b/.idea/libraries/Maven__org_apache_extras_beanshell_bsh_2_0b6.xml new file mode 100644 index 0000000..3b84834 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_extras_beanshell_bsh_2_0b6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml new file mode 100644 index 0000000..f58bbc1 --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_testng_testng_6_14_3.xml b/.idea/libraries/Maven__org_testng_testng_6_14_3.xml new file mode 100644 index 0000000..3e0d80c --- /dev/null +++ b/.idea/libraries/Maven__org_testng_testng_6_14_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..71e13c4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..db2f06c --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MultiThreadDP.iml b/MultiThreadDP.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/MultiThreadDP.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0ceaf57 --- /dev/null +++ b/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + com.xycode + MultiThreadPro + 1.0-SNAPSHOT + + + jdk-1.8 + + true + 1.8 + + + + 1.8 + 1.8 + 1.8 + + + + + + + org.testng + testng + 6.14.3 + + + + junit + junit + 4.12 + compile + + + + \ No newline at end of file diff --git a/src/com/xycode/aqsLock/MyLock.java b/src/com/xycode/aqsLock/MyLock.java new file mode 100644 index 0000000..b318702 --- /dev/null +++ b/src/com/xycode/aqsLock/MyLock.java @@ -0,0 +1,165 @@ +package com.xycode.aqsLock; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.concurrent.*; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * ClassName: MyLock + * + * @Author: xycode + * @Date: 2019/10/30 + * @Description: this is description of the MyLock class + **/ +public class MyLock implements Lock { + private MySync sync; + + public MyLock() { + this.sync = new MySync(); + } + + @Override + public void lock() { + sync.acquire(1);//锁计数加一 + } + + @Override + public void lockInterruptibly() throws InterruptedException { + sync.acquireInterruptibly(1); + } + + @Override + public boolean tryLock() { + return sync.tryAcquire(1); + } + + @Override + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { + return sync.tryAcquireNanos(1,unit.toNanos(time)); + } + + @Override + public void unlock() { + sync.release(1);//锁计数减一 + } + + @Override + public Condition newCondition() { + return sync.newCondition(); + } + + + private static class MySync extends AbstractQueuedSynchronizer { + @Override + protected boolean tryAcquire(int arg) {//arg是锁计数增量 + if(getState()==0){//state==0说明没有其它线程占用锁 + if(compareAndSetState(0,arg)){//CAS操作,将state设置为arg + setExclusiveOwnerThread(Thread.currentThread());//设置为当前线程独占这个锁 + return true;//成功获得锁 + } + }else if(Thread.currentThread()==getExclusiveOwnerThread()){//同一个线程多次lock,即重入锁 + setState(getState()+1);//当前线程的锁计数加一 + return true; + } + return false;//获锁失败 + } + + @Override + protected boolean tryRelease(int arg) { + //lock与unlock是一一对应的,即必须是同一个线程执行 + if(Thread.currentThread()!=getExclusiveOwnerThread()){ + throw new RuntimeException("unlock error"); + } + int state=getState()-arg; + boolean released=false; + if(state==0){//锁计数为0,释放成功 + setExclusiveOwnerThread(null); + released=true; + } + setState(state); + return released; + } + + final ConditionObject newCondition(){ + return new ConditionObject(); + } + } + + + @Test + public void testWithoutMyLock(){ + final int[] cnt={0}; + Thread[] t=new Thread[10]; + final CountDownLatch countDownLatch=new CountDownLatch(t.length); + for(int i=0;i exchanger=new Exchanger<>(); + final CountDownLatch countDownLatch=new CountDownLatch(2); + new Thread(){ + @Override + public void run() { + Thread thread=Thread.currentThread(); + try { + TimeUnit.SECONDS.sleep(1); + System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); + System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 + countDownLatch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + new Thread(){ + @Override + public void run() { + Thread thread=Thread.currentThread(); + try { + TimeUnit.SECONDS.sleep(3);//这里要慢一点,实际上另一端即使早到达交换点,也会阻塞在那儿,直到这段也到达交换点 + System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); + System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 + countDownLatch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + }.start(); + + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/xycode/observer/BinaryObserver.java b/src/com/xycode/observer/BinaryObserver.java new file mode 100644 index 0000000..9a4ce9d --- /dev/null +++ b/src/com/xycode/observer/BinaryObserver.java @@ -0,0 +1,13 @@ +package com.xycode.observer; + +public class BinaryObserver extends Observer{ + + public BinaryObserver(Subject subject){ + this.subject=subject; + + } + @Override + public void update() { + System.out.println("BinaryObserver : "+Integer.toBinaryString(subject.getState())); + } +} diff --git a/src/com/xycode/observer/Main.java b/src/com/xycode/observer/Main.java new file mode 100644 index 0000000..f75f4a1 --- /dev/null +++ b/src/com/xycode/observer/Main.java @@ -0,0 +1,18 @@ +package com.xycode.observer; + +public class Main { + public static void main(String[] args) { + final Subject subject=new Subject(); + subject.attach(new BinaryObserver(subject)); + + subject.attach(new OctalObserver(subject)); + + subject.setState(100);//BinaryObserver与OctalObserver会监听到这个set,并打印信息 + } +} + + + + + + diff --git a/src/com/xycode/observer/Observer.java b/src/com/xycode/observer/Observer.java new file mode 100644 index 0000000..fc23803 --- /dev/null +++ b/src/com/xycode/observer/Observer.java @@ -0,0 +1,7 @@ +package com.xycode.observer; + +public abstract class Observer { + public Subject subject; + public abstract void update(); +} + diff --git a/src/com/xycode/observer/OctalObserver.java b/src/com/xycode/observer/OctalObserver.java new file mode 100644 index 0000000..c5cf239 --- /dev/null +++ b/src/com/xycode/observer/OctalObserver.java @@ -0,0 +1,12 @@ +package com.xycode.observer; + +public class OctalObserver extends Observer { + + public OctalObserver(Subject subject){ + this.subject=subject; + } + @Override + public void update() { + System.out.println("OctalObserver : "+Integer.toOctalString(subject.getState())); + } +} diff --git a/src/com/xycode/observer/Subject.java b/src/com/xycode/observer/Subject.java new file mode 100644 index 0000000..3351f0f --- /dev/null +++ b/src/com/xycode/observer/Subject.java @@ -0,0 +1,29 @@ +package com.xycode.observer; + +import java.util.ArrayList; +import java.util.List; + +public class Subject { + private List observers=new ArrayList<>(); + private int state; + + public void setState(int state) { + if(state==this.state) return; + this.state = state; + notifyAllObserver(); + } + + public int getState() { + return state; + } + + public void attach(Observer observer){ + observers.add(observer); + } + + private void notifyAllObserver(){ + observers.stream().forEach(Observer::update); + //函数式编程,对每个Observer都执行update方法 + } + +} diff --git a/src/com/xycode/spinlock/MySpinLock.java b/src/com/xycode/spinlock/MySpinLock.java new file mode 100644 index 0000000..e1c8427 --- /dev/null +++ b/src/com/xycode/spinlock/MySpinLock.java @@ -0,0 +1,49 @@ +package com.xycode.spinlock; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +/** + * ClassName: MySpinLock + * + * @Author: xycode + * @Date: 2019/10/28 + **/ +public class MySpinLock { + private AtomicReference atomicReference=new AtomicReference<>(null); + public void lock(){//实现自旋锁,CPU占用较高 + Thread thread=Thread.currentThread(); + while(!atomicReference.compareAndSet(null,thread)){ +// System.err.println("Thread-"+thread.getId()+" fail to acquire lock"); + } + } + + public void unlock(){ + Thread thread=Thread.currentThread(); + atomicReference.compareAndSet(thread,null); + } + + public static void main(String[] args) { + Thread[] t=new Thread[5]; + MySpinLock spinLock=new MySpinLock(); + for(int i=0;i{ + try { + spinLock.lock(); + System.out.println("Thread-"+Thread.currentThread().getId()+" acquire lock"); + System.out.println("Thread-"+Thread.currentThread().getId()+" working..."); + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Thread-"+Thread.currentThread().getId()+" release lock"); + System.out.println(); + }finally { + spinLock.unlock(); + } + }); + } + for(Thread thread:t) thread.start(); + } +} diff --git a/src/com/xycode/synchronizedDemo/LockObject.java b/src/com/xycode/synchronizedDemo/LockObject.java new file mode 100644 index 0000000..eb8434d --- /dev/null +++ b/src/com/xycode/synchronizedDemo/LockObject.java @@ -0,0 +1,95 @@ +package com.xycode.synchronizedDemo; + +import java.util.concurrent.TimeUnit; + +public class LockObject { + public static int cnt=0; + public static int cnt2=0; + public static int cnt3=0; + public static int cnt4=0; + //在这里synchronized(this){}与synchronized修饰方法的效果是一样的 + public void inc(){ + try { + TimeUnit.MILLISECONDS.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (this){ + ++cnt; + } + } + + public synchronized void inc2(){ + ++cnt2; + } + + //在这里,每调用inc3()一次,就会新建一个Object实例,对比以上两种使用方式,这种方式的锁粒度更细 + //但是,这种加锁方式是不安全的,因为方法内的Object实例只约束到了当前调用线程, + //当有多个线程同时调用时,线程彼此之间起不到互斥作用! +// public void inc3(){ +// Object o=new Object(); +// synchronized (o){ +// ++cnt3; +// } +// } + + //上面的inc3()改成这样就线程安全了,因为lock是LockObject的成员变量,和this是一一对应的, + // 效果也和synchronized(this){}一样 + Object lock=new Object(); + public void inc3(){ + synchronized (lock){ + ++cnt3; + } + } + + //下面这个实际上和synchronized(class){]效果一样了,锁的限制更强了,会约束全体LockObject实例 + //详细的验证见LockStatic.java + private static Object staticLock=new Object(); + public void inc4(){ + synchronized (staticLock){ + ++cnt4; + } + } + + public static void main(String[] args) { + Thread[] t=new Thread[200]; + //因为只有一个LockObject实例,所以synchronized起到了同步的作用 + LockObject lockObject=new LockObject(); + for(int i=0;i + diff --git a/.idea/dictionaries/xycode.xml b/.idea/dictionaries/xycode.xml index 1e05936..1e9f429 100644 --- a/.idea/dictionaries/xycode.xml +++ b/.idea/dictionaries/xycode.xml @@ -1,6 +1,7 @@ + reentrant xycode diff --git a/.idea/libraries/Maven__org_openjdk_jol_jol_core_0_9.xml b/.idea/libraries/Maven__org_openjdk_jol_jol_core_0_9.xml new file mode 100644 index 0000000..366b137 --- /dev/null +++ b/.idea/libraries/Maven__org_openjdk_jol_jol_core_0_9.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0ceaf57..d020549 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,13 @@ 6.14.3 + + + org.openjdk.jol + jol-core + 0.9 + + junit junit diff --git a/src/com/xycode/exchanger/ExchangerDemo_1.java b/src/com/xycode/exchanger/ExchangerDemo_1.java index 688b013..0350df4 100644 --- a/src/com/xycode/exchanger/ExchangerDemo_1.java +++ b/src/com/xycode/exchanger/ExchangerDemo_1.java @@ -1,9 +1,10 @@ package com.xycode.exchanger; -import java.util.Random; +import java.sql.Time; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Exchanger; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; /** * ClassName: Demo_1 @@ -51,5 +52,6 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } + } } diff --git a/src/com/xycode/spinlock/MyReentrantSpinLock.java b/src/com/xycode/spinlock/MyReentrantSpinLock.java new file mode 100644 index 0000000..4060c97 --- /dev/null +++ b/src/com/xycode/spinlock/MyReentrantSpinLock.java @@ -0,0 +1,14 @@ +package com.xycode.spinlock; + +import java.util.concurrent.locks.ReentrantLock; + +/** + * ClassName: MyReentrantSpinLock + * + * @Author: xycode + * @Date: 2019/11/7 + * @Description: this is description of the MyReentrantSpinLock class + **/ +public class MyReentrantSpinLock { + +} diff --git a/src/com/xycode/spinlock/MySpinLock.java b/src/com/xycode/spinlock/MySpinLock.java index e1c8427..e47ab73 100644 --- a/src/com/xycode/spinlock/MySpinLock.java +++ b/src/com/xycode/spinlock/MySpinLock.java @@ -15,6 +15,7 @@ public void lock(){//实现自旋锁,CPU占用较高 Thread thread=Thread.currentThread(); while(!atomicReference.compareAndSet(null,thread)){ // System.err.println("Thread-"+thread.getId()+" fail to acquire lock"); + thread.yield();//让出CPU,减少锁竞争,不过不保证一定有效... } } diff --git a/src/com/xycode/synchronizedDemo/LockObject.java b/src/com/xycode/synchronizedDemo/LockObject.java index eb8434d..cea7371 100644 --- a/src/com/xycode/synchronizedDemo/LockObject.java +++ b/src/com/xycode/synchronizedDemo/LockObject.java @@ -8,6 +8,8 @@ public class LockObject { public static int cnt3=0; public static int cnt4=0; //在这里synchronized(this){}与synchronized修饰方法的效果是一样的 + + Object lock=new Object(); public void inc(){ try { TimeUnit.MILLISECONDS.sleep(200); @@ -35,7 +37,6 @@ public synchronized void inc2(){ //上面的inc3()改成这样就线程安全了,因为lock是LockObject的成员变量,和this是一一对应的, // 效果也和synchronized(this){}一样 - Object lock=new Object(); public void inc3(){ synchronized (lock){ ++cnt3; diff --git a/src/com/xycode/synchronizedDemo/Test.java b/src/com/xycode/synchronizedDemo/Test.java new file mode 100644 index 0000000..acc83f2 --- /dev/null +++ b/src/com/xycode/synchronizedDemo/Test.java @@ -0,0 +1,24 @@ +package com.xycode.synchronizedDemo; + +import org.openjdk.jol.info.ClassLayout; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; + +/** + * ClassName: Test + * + * @Author: xycode + * @Date: 2019/11/9 + * @Description: this is description of the Test class + **/ +public class Test { + static class test{ + int i=0; + byte[] array=new byte[100]; + } + public static void main(String[] args) { + System.out.println(ClassLayout.parseInstance(new test()).toPrintable()); + + } +} From 910d7bd8694ef2a970ec52d00ad4937f487a344a Mon Sep 17 00:00:00 2001 From: xycodec Date: Sun, 23 Feb 2020 02:06:13 +0800 Subject: [PATCH 3/4] [update]: 2020.2.23 --- .idea/MultiThreadPro.iml | 6 + dependency-reduced-pom.xml | 40 ++++++ pom.xml | 27 +++- src/com/xycode/TestReference.java | 104 ++++++++++++++ src/com/xycode/aqsLock/MyLock.java | 54 +++---- src/com/xycode/exchanger/ExchangerDemo_1.java | 47 +++--- src/com/xycode/executor/Demo_1.java | 50 +++++++ .../xycode/synchronizedDemo/LockObject.java | 1 + .../LockPromote/ObjectHeader.java | 134 ++++++++++++++++++ src/com/xycode/synchronizedDemo/Test.java | 24 ---- 10 files changed, 404 insertions(+), 83 deletions(-) create mode 100644 dependency-reduced-pom.xml create mode 100644 src/com/xycode/TestReference.java create mode 100644 src/com/xycode/executor/Demo_1.java create mode 100644 src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java delete mode 100644 src/com/xycode/synchronizedDemo/Test.java diff --git a/.idea/MultiThreadPro.iml b/.idea/MultiThreadPro.iml index 3732743..85b1662 100644 --- a/.idea/MultiThreadPro.iml +++ b/.idea/MultiThreadPro.iml @@ -1,11 +1,17 @@ + + + + + + diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..32b0426 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + com.xycode + MultiThreadPro + 1.0-SNAPSHOT + + + + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + com.xycode.synchronizedDemo.LockPromote.ObjectHeader + + + + + + + + + + + jdk-1.8 + + 1.8 + 1.8 + 1.8 + + + + diff --git a/pom.xml b/pom.xml index d020549..e1fab39 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,31 @@ + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + com.xycode.synchronizedDemo.LockPromote.ObjectHeader + + + + + + + + + org.testng @@ -41,7 +66,7 @@ junit junit 4.12 - compile + diff --git a/src/com/xycode/TestReference.java b/src/com/xycode/TestReference.java new file mode 100644 index 0000000..fe0b0f4 --- /dev/null +++ b/src/com/xycode/TestReference.java @@ -0,0 +1,104 @@ +package com.xycode; + +import org.junit.Test; +import org.openjdk.jol.info.ClassLayout; +import org.testng.Assert; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.util.Map; +import java.util.Objects; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * ClassName: Test + * + * @Author: xycode + * @Date: 2019/11/9 + * @Description: this is description of the Test class + **/ +public class TestReference { + static class test{ + int i=0; + byte[] array=new byte[100]; + } + + @Test + public void test_1(){ + Map mp1=new ConcurrentHashMap(){ + { + put("1","one"); + put("2","two"); + put("3","three"); + } + }; + Map mp2=new ConcurrentHashMap(){ + { + put("one","1"); + put("two","2"); + put("three","3"); + } + }; + Assert.assertEquals(mp1.get("xxx"),null); + Assert.assertEquals(mp2.get("xxx"),null); + System.out.println(mp1); + System.out.println(mp2); + Assert.assertEquals(mp1.containsKey("1"),true); + Assert.assertEquals(mp2.containsKey("one"),true); + for(String key:mp1.keySet()){ + Assert.assertNotEquals(mp2.remove(mp1.remove(key)),null); + } + Assert.assertEquals(mp1.isEmpty(),true); + Assert.assertEquals(mp2.isEmpty(),true); + + } + + public static void main(String[] args) { + +// Semaphore semaphore=new Semaphore(1); +// try { +// semaphore.acquire(); +// semaphore.acquire(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// }finally { +// semaphore.release(); +// semaphore.release(); +// } +// +// ReentrantLock lock=new ReentrantLock(); +// lock.lock(); +// Condition condition=lock.newCondition(); +// try { +// condition.await(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// lock.unlock(); + + //幽灵引用示例 + Object o=new Object(); + ReferenceQueue referenceQueue=new ReferenceQueue<>(); + PhantomReference phantomReference=new PhantomReference(o,referenceQueue); + + System.out.println(o); + System.out.println(phantomReference); + System.out.println(phantomReference.get()); + System.out.println(referenceQueue.poll()); + + System.out.println("-------------------------"); + + o=null; + System.gc(); + System.out.println(o); + System.out.println(phantomReference); + System.out.println(phantomReference.get()); + System.out.println(referenceQueue.poll()); + } +} diff --git a/src/com/xycode/aqsLock/MyLock.java b/src/com/xycode/aqsLock/MyLock.java index b318702..40e2721 100644 --- a/src/com/xycode/aqsLock/MyLock.java +++ b/src/com/xycode/aqsLock/MyLock.java @@ -97,17 +97,14 @@ public void testWithoutMyLock(){ Thread[] t=new Thread[10]; final CountDownLatch countDownLatch=new CountDownLatch(t.length); for(int i=0;i { + for(int i1 = 0; i1 <10000; ++i1){ + ++cnt[0]; } - }; + countDownLatch.countDown(); + }); } - for(int i=0;i { + try { + lock.lock();//可重入锁 + lock.lock(); + for(int i1 = 0; i1 <10000; ++i1){ + ++cnt[0]; + } + }finally { + lock.unlock(); + lock.unlock(); try { - lock.lock();//可重入锁 - lock.lock(); - for(int i=0;i<10000;++i){ - ++cnt[0]; - } - }finally { - lock.unlock(); - lock.unlock(); - try { - cyclicBarrier.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (BrokenBarrierException e) { - e.printStackTrace(); - } + cyclicBarrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + e.printStackTrace(); } } - }; + }); } - for(int i=0;i exchanger=new Exchanger<>(); final CountDownLatch countDownLatch=new CountDownLatch(2); - new Thread(){ - @Override - public void run() { - Thread thread=Thread.currentThread(); - try { - TimeUnit.SECONDS.sleep(1); - System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); - System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 - countDownLatch.countDown(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + new Thread(() -> { + Thread thread=Thread.currentThread(); + try { + TimeUnit.SECONDS.sleep(1); + System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); + System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 + countDownLatch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); } - }.start(); - new Thread(){ - @Override - public void run() { - Thread thread=Thread.currentThread(); - try { - TimeUnit.SECONDS.sleep(3);//这里要慢一点,实际上另一端即使早到达交换点,也会阻塞在那儿,直到这段也到达交换点 - System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); - System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 - countDownLatch.countDown(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + }).start(); + new Thread(() -> { + Thread thread=Thread.currentThread(); + try { + TimeUnit.SECONDS.sleep(3);//这里要慢一点,实际上另一端即使早到达交换点,也会阻塞在那儿,直到这段也到达交换点 + System.out.println("Thread-"+thread.getId()+" arrive exchange point..."); + System.out.println("Thread-"+thread.getId()+" get peer's ID = "+exchanger.exchange(thread.getId()));//交换点 + countDownLatch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); } - }.start(); + + }).start(); try { countDownLatch.await(); diff --git a/src/com/xycode/executor/Demo_1.java b/src/com/xycode/executor/Demo_1.java new file mode 100644 index 0000000..823a441 --- /dev/null +++ b/src/com/xycode/executor/Demo_1.java @@ -0,0 +1,50 @@ +package com.xycode.executor; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * ClassName: Demo_1 + * + * @Author: xycode + * @Date: 2019/11/29 + * @Description: this is description of the Demo_1 class + **/ +public class Demo_1 { + public static void main(String[] args) { + ExecutorService es= Executors.newSingleThreadExecutor(); + es.submit(()->{ + int count=0; + while(true){ + if(count>=2) break; + System.out.println(Thread.currentThread().getName()+" started"); + try { + TimeUnit.SECONDS.sleep(3); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName()+" done"); + ++count; + } + + }); + + es.shutdown(); +// try { +// es.awaitTermination(100,TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// es.shutdownNow();//对于while(true)的任务,除非自行停止,否则是停止不了的 + while(true){ + System.out.println(es.isTerminated()); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/com/xycode/synchronizedDemo/LockObject.java b/src/com/xycode/synchronizedDemo/LockObject.java index cea7371..cc9bc37 100644 --- a/src/com/xycode/synchronizedDemo/LockObject.java +++ b/src/com/xycode/synchronizedDemo/LockObject.java @@ -1,6 +1,7 @@ package com.xycode.synchronizedDemo; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; public class LockObject { public static int cnt=0; diff --git a/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java b/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java new file mode 100644 index 0000000..112604a --- /dev/null +++ b/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java @@ -0,0 +1,134 @@ +package com.xycode.synchronizedDemo.LockPromote; + +import org.openjdk.jol.info.ClassLayout; + +import java.nio.ByteOrder; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * ClassName: Main + * + * @Author: xycode + * @Date: 2019/11/28 + * @Description: this is description of the Main class + **/ +public class ObjectHeader { + static class Obj{ + int i=0; +// byte[] array=new byte[100]; + } + + public static String getObjectHeader(Object o){ + ByteOrder order=ByteOrder.nativeOrder();//字节序 + String table=ClassLayout.parseInstance(o).toPrintable(); + Pattern p=Pattern.compile("(0|1){8}"); + Matcher matcher=p.matcher(table); + List header=new ArrayList<>(); + while(matcher.find()){ + header.add(matcher.group()); + } + //小端机器,需要反过来遍历 + StringBuilder sb=new StringBuilder(); + if(order.equals(ByteOrder.LITTLE_ENDIAN)){ + Collections.reverse(header); + } + for(String s:header){ + sb.append(s).append(" "); + } + return sb.toString().trim(); + } + + /** + * 针对64bit jvm的解析对象头函数 + * 在64bit jvm中,对象头有两个部分: Mark Word和Class Pointer, Mark Word占8字节,Class Pointer占4字节 + * @param s 对象头的二进制形式字符串(每8位,使用一个空格分开) + */ + public static void parseObjectHeader(String s){ + String[] tmp=s.split(" "); + System.out.print("Class Pointer: "); + for(int i=0;i<4;++i){ + System.out.print(tmp[i]+" "); + } + System.out.println("\nMark Word:"); + if(tmp[11].charAt(5)=='0'&&tmp[11].substring(6).equals("01")){//0 01无锁状态,不考虑GC标记的情况 + //notice: 无锁情况下mark word的结构: unused(25bit) + hashcode(31bit) + unused(1bit) + age(4bit) + biased_lock_flag(1bit) + lock_type(2bit) + // hashcode只需要31bit的原因是: hashcode只能大于等于0,省去了负数范围,所以使用31bit就可以存储 + System.out.print("\thashcode (31bit): "); + System.out.print(tmp[7].substring(1)+" "); + for(int i=8;i<11;++i) System.out.print(tmp[i]+" "); + System.out.println(); + }else if(tmp[11].charAt(5)=='1'&&tmp[11].substring(6).equals("01")){//1 01,即偏向锁的情况 + //notice: 对象处于偏向锁的情况,其结构为: ThreadID(54bit) + epoch(2bit) + unused(1bit) + age(4bit) + biased_lock_flag(1bit) + lock_type(2bit) + // 这里的ThreadID是持有偏向锁的线程ID, epoch: 一个偏向锁的时间戳,用于偏向锁的优化 + System.out.print("\tThreadID(54bit): "); + for(int i=4;i<10;++i) System.out.print(tmp[i]+" "); + System.out.println(tmp[10].substring(0,6)); + System.out.println("\tepoch: "+tmp[10].substring(6)); + }else{//轻量级锁或重量级锁的情况,不考虑GC标记的情况 + //notice: JavaThread*(62bit,include zero padding) + lock_type(2bit) + // 此时JavaThread*指向的是 栈中锁记录/重量级锁的monitor + System.out.print("\tjavaThread*(62bit,include zero padding): "); + for(int i=4;i<11;++i) System.out.print(tmp[i]+" "); + System.out.println(tmp[11].substring(0,6)); + System.out.println("\tLockFlag (2bit): "+tmp[11].substring(6)); + System.out.println(); + return; + } + System.out.println("\tage (4bit): "+tmp[11].substring(1,5)); + System.out.println("\tbiasedLockFlag (1bit): "+tmp[11].charAt(5)); + System.out.println("\tLockFlag (2bit): "+tmp[11].substring(6)); + + System.out.println(); + } + + + public static void main(String[] args) { + /** + * Mark Word 占 8 字节 + * Class Pointer 占 4 字节 + * + * 偏向锁标志位(1bit,1表示有偏向锁)+锁状态位(2bit) + * (1)01: 偏向锁 + * (0)01: 无锁 + * + * 00: 轻量级锁 + * 10: 重量级锁 + * + * 11: GC标记,当为该值是,偏向锁标志位必定为0 + */ + Obj o=new Obj(); +// 测试synchronized锁升级的情况,若要立即查看测试情况,需要禁止偏向锁延迟: -XX:BiasedLockingStartupDelay=0 +// 开启偏向锁: -XX:+UseBiasedLocking=0, jdk6开始就默认开启了,不开启就是先使用轻量级锁 +// System.out.println(o.hashCode());//notice: 调用hashcode后就没有偏向锁了...(因为bit位置被占了) + + //main线程,偏向锁 + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + //轻量级锁,因为下面的线程又占用了o + new Thread(()->{ + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + }).start(); + + //重量级锁 +// for(int i=0;i<2;++i)//线程数大于1时(交错执行),会升级成重量级锁 +// new Thread(()->{ +// synchronized (o){ +// parseObjectHeader(getObjectHeader(o)); +// } +// }).start(); + + + //测试hashcode,并且会导致不能偏向锁 +// parseObjectHeader(getObjectHeader(o)); +// System.out.println(o.hashCode()); +// System.gc();//会增加一次分代年龄,连续调用好像只能起一次效果 +// parseObjectHeader(getObjectHeader(o)); + + } +} diff --git a/src/com/xycode/synchronizedDemo/Test.java b/src/com/xycode/synchronizedDemo/Test.java deleted file mode 100644 index acc83f2..0000000 --- a/src/com/xycode/synchronizedDemo/Test.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.xycode.synchronizedDemo; - -import org.openjdk.jol.info.ClassLayout; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; - -/** - * ClassName: Test - * - * @Author: xycode - * @Date: 2019/11/9 - * @Description: this is description of the Test class - **/ -public class Test { - static class test{ - int i=0; - byte[] array=new byte[100]; - } - public static void main(String[] args) { - System.out.println(ClassLayout.parseInstance(new test()).toPrintable()); - - } -} From d890b4f66f262d940bd5f5b3f14b90f00245cc43 Mon Sep 17 00:00:00 2001 From: xycodec Date: Sun, 29 Mar 2020 01:13:05 +0800 Subject: [PATCH 4/4] 2020.3.29 --- .idea/dictionaries/xycode.xml | 1 + .idea/inspectionProfiles/Project_Default.xml | 36 ++ src/com/xycode/TestReference.java | 104 ----- src/com/xycode/Tests.java | 202 ++++++++++ src/com/xycode/countEx/ConditionCount.java | 86 ++++ .../xycode/countEx/CountDownLatchCount.java | 78 ++++ src/com/xycode/countEx/SynchronizedCount.java | 74 ++++ .../cyclicBarrierDemo/CyclicBarrierDemo1.java | 5 +- src/com/xycode/executor/MyConnectionPool.java | 377 ++++++++++++++++++ .../myThreadPool/MyBlockingQueue.java | 148 +++++++ .../myThreadPool/MyRejectStrategy.java | 14 + .../executor/myThreadPool/MyThreadPool.java | 118 ++++++ src/com/xycode/hashMap/TestHashMap7.java | 17 + .../LockPromote/ObjectHeader.java | 58 ++- src/com/xycode/unsafe/MyAtomicInteger.java | 71 ++++ src/com/xycode/unsafe/TestUnsafe.java | 52 +++ src/com/xycode/unsafe/UnsafeUtils.java | 33 ++ 17 files changed, 1364 insertions(+), 110 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 src/com/xycode/TestReference.java create mode 100644 src/com/xycode/Tests.java create mode 100644 src/com/xycode/countEx/ConditionCount.java create mode 100644 src/com/xycode/countEx/CountDownLatchCount.java create mode 100644 src/com/xycode/countEx/SynchronizedCount.java create mode 100644 src/com/xycode/executor/MyConnectionPool.java create mode 100644 src/com/xycode/executor/myThreadPool/MyBlockingQueue.java create mode 100644 src/com/xycode/executor/myThreadPool/MyRejectStrategy.java create mode 100644 src/com/xycode/executor/myThreadPool/MyThreadPool.java create mode 100644 src/com/xycode/hashMap/TestHashMap7.java create mode 100644 src/com/xycode/unsafe/MyAtomicInteger.java create mode 100644 src/com/xycode/unsafe/TestUnsafe.java create mode 100644 src/com/xycode/unsafe/UnsafeUtils.java diff --git a/.idea/dictionaries/xycode.xml b/.idea/dictionaries/xycode.xml index 1e9f429..f98e000 100644 --- a/.idea/dictionaries/xycode.xml +++ b/.idea/dictionaries/xycode.xml @@ -1,6 +1,7 @@ + nanos reentrant xycode diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6560a98 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff --git a/src/com/xycode/TestReference.java b/src/com/xycode/TestReference.java deleted file mode 100644 index fe0b0f4..0000000 --- a/src/com/xycode/TestReference.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.xycode; - -import org.junit.Test; -import org.openjdk.jol.info.ClassLayout; -import org.testng.Assert; - -import java.lang.ref.PhantomReference; -import java.lang.ref.ReferenceQueue; -import java.util.Map; -import java.util.Objects; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * ClassName: Test - * - * @Author: xycode - * @Date: 2019/11/9 - * @Description: this is description of the Test class - **/ -public class TestReference { - static class test{ - int i=0; - byte[] array=new byte[100]; - } - - @Test - public void test_1(){ - Map mp1=new ConcurrentHashMap(){ - { - put("1","one"); - put("2","two"); - put("3","three"); - } - }; - Map mp2=new ConcurrentHashMap(){ - { - put("one","1"); - put("two","2"); - put("three","3"); - } - }; - Assert.assertEquals(mp1.get("xxx"),null); - Assert.assertEquals(mp2.get("xxx"),null); - System.out.println(mp1); - System.out.println(mp2); - Assert.assertEquals(mp1.containsKey("1"),true); - Assert.assertEquals(mp2.containsKey("one"),true); - for(String key:mp1.keySet()){ - Assert.assertNotEquals(mp2.remove(mp1.remove(key)),null); - } - Assert.assertEquals(mp1.isEmpty(),true); - Assert.assertEquals(mp2.isEmpty(),true); - - } - - public static void main(String[] args) { - -// Semaphore semaphore=new Semaphore(1); -// try { -// semaphore.acquire(); -// semaphore.acquire(); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// }finally { -// semaphore.release(); -// semaphore.release(); -// } -// -// ReentrantLock lock=new ReentrantLock(); -// lock.lock(); -// Condition condition=lock.newCondition(); -// try { -// condition.await(); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// lock.unlock(); - - //幽灵引用示例 - Object o=new Object(); - ReferenceQueue referenceQueue=new ReferenceQueue<>(); - PhantomReference phantomReference=new PhantomReference(o,referenceQueue); - - System.out.println(o); - System.out.println(phantomReference); - System.out.println(phantomReference.get()); - System.out.println(referenceQueue.poll()); - - System.out.println("-------------------------"); - - o=null; - System.gc(); - System.out.println(o); - System.out.println(phantomReference); - System.out.println(phantomReference.get()); - System.out.println(referenceQueue.poll()); - } -} diff --git a/src/com/xycode/Tests.java b/src/com/xycode/Tests.java new file mode 100644 index 0000000..8bf818b --- /dev/null +++ b/src/com/xycode/Tests.java @@ -0,0 +1,202 @@ +package com.xycode; + +import com.xycode.unsafe.UnsafeUtils; +import org.junit.Test; +import org.testng.Assert; + +import javax.xml.ws.WebEndpoint; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +/** + * ClassName: Test + * + * @Author: xycode + * @Date: 2019/11/9 + * @Description: this is description of the Test class + **/ +public class Tests { + public static class test{ +// int i=j;//static internal class can only access to external class's static variables + //non-static internal class can access to external class's non-static/static variables + byte[] array=new byte[100]; + Tests tests =new Tests(); + } + +// int j=0; + @Test + public void test_1(){ + Map mp1=new ConcurrentHashMap(){ + { + put("1","one"); + put("2","two"); + put("3","three"); + } + }; + Map mp2=new ConcurrentHashMap(){ + { + put("one","1"); + put("two","2"); + put("three","3"); + } + }; + Assert.assertEquals(mp1.get("xxx"),null); + Assert.assertEquals(mp2.get("xxx"),null); + System.out.println(mp1); + System.out.println(mp2); + Assert.assertEquals(mp1.containsKey("1"),true); + Assert.assertEquals(mp2.containsKey("one"),true); + for(String key:mp1.keySet()){ + Assert.assertNotEquals(mp2.remove(mp1.remove(key)),null); + } + Assert.assertEquals(mp1.isEmpty(),true); + Assert.assertEquals(mp2.isEmpty(),true); + + } + + public static String transfer(String s){ + System.out.println("--> transfer..."); + return s.toUpperCase(); + } + + public static String func(){ + try { + System.out.println("try..."); + String result="returnStr"; +// System.out.println(result); + return transfer(result); + }finally { + System.out.println("finally..."); + } + } + + public static void main(String[] args) throws InterruptedException { + +// Semaphore semaphore=new Semaphore(1); +// try { +// semaphore.acquire(); +// semaphore.acquire(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// }finally { +// semaphore.release(); +// semaphore.release(); +// } +// +// ReentrantLock lock=new ReentrantLock(); +// lock.lock(); +// Condition condition=lock.newCondition(); +// try { +// condition.await(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// lock.unlock(); + +// //notice: 幽灵引用示例 +// Object o=new Object(); +// ReferenceQueue referenceQueue=new ReferenceQueue<>(); +// PhantomReference phantomReference=new PhantomReference(o,referenceQueue); +// +// System.out.println(o); +// System.out.println(phantomReference); +// System.out.println(phantomReference.get()); +// System.out.println(referenceQueue.poll()); +// +// System.out.println("-------------------------"); +// +// o=null; +// System.gc(); +// System.out.println(o); +// System.out.println(phantomReference); +// System.out.println(phantomReference.get()); +// System.out.println(referenceQueue.poll()); + + + +// Thread t1=new Thread(()->{ +// System.out.println(Thread.currentThread().getName()+": "+Thread.currentThread().getState()); +// LockSupport.park(); +// System.out.println(Thread.currentThread().getName()+": "+Thread.currentThread().getState()); +// }); +// +// System.out.println(t1.getName()+": "+t1.getState()); +// t1.start(); +// TimeUnit.SECONDS.sleep(1); +// System.out.println(t1.getName()+": "+t1.getState()); +// TimeUnit.SECONDS.sleep(1); +// LockSupport.unpark(t1); + + //测试finally +// System.out.println(func()); + +// ExecutorService es=new ThreadPoolExecutor(2, 5, +// 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), new ThreadFactory() { +// private AtomicInteger atomicInteger=new AtomicInteger(0); +// @Override +// public Thread newThread(Runnable r) { +// System.out.println(atomicInteger.incrementAndGet()+": thread created, "); +// return new Thread(r,"thread-"+atomicInteger.get()); +// } +// }); + //notice: 证明超过coreSize的任务会先被添加到任务队列里面 + // 最终线程池的容量: maximumPoolSize + taskQueue.capacity; +// for(int i=0;i<8;++i){ +// es.submit(new Runnable() { +// @Override +// public void run() { +// try { +// TimeUnit.SECONDS.sleep(1); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// System.out.println(Thread.currentThread().getName()+"'s task, "+es.toString()); +// } +// }); +// } +// +// es.shutdown(); +// +// System.out.println("main end"); + + //notice: 反射调用方法,实际上也能实现AOP,但是这种方式对调用者的侵入性太强, + // 即必须提供方法名参数(类似这样,invoke(方法名参数)),而不是直接.method()来调用 +// A a=new A("xycode"); +// try { +// a.getClass().getMethod("sayName").invoke(a); +// } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { +// e.printStackTrace(); +// } + + Map mp=new HashMap<>(); + mp.put(1,1234); + for(Map.Entry entry:mp.entrySet()){ + System.out.println(entry.getKey()+":"+entry.getValue()); + } + mp.forEach((key,value)->System.out.println(key+":"+value)); + + Thread t=new Thread(); + + } + + static class A{ + String name; + public A(String name) { + this.name = name; + } + public void sayName(){ + System.out.println(this.name); + } + } + + +} diff --git a/src/com/xycode/countEx/ConditionCount.java b/src/com/xycode/countEx/ConditionCount.java new file mode 100644 index 0000000..d03518d --- /dev/null +++ b/src/com/xycode/countEx/ConditionCount.java @@ -0,0 +1,86 @@ +package com.xycode.countEx; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * ClassName: ConditionCount + * + * @Author: xycode + * @Date: 2020/3/28 + * @Description: 使用ReentrantLock + Condition实现3个线程交替计数 + **/ +public class ConditionCount { + private static final int threshold=100; + private AtomicInteger cnt=new AtomicInteger(1); + ReentrantLock lock=new ReentrantLock(); + Condition ab=lock.newCondition(),bc=lock.newCondition(),ca=lock.newCondition(); + public void countA(){ + while(true){ + lock.lock(); + try { + if(cnt.intValue()>threshold) { + ab.signal(); + return; + } + ca.await(); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + ab.signal(); + } catch (InterruptedException e) { + e.printStackTrace(); + }finally { + lock.unlock(); + } + + } + } + + public void countB(){ + while(true){ + lock.lock(); + try { + if(cnt.intValue()>threshold) { + bc.signal(); + return; + } + ab.await(); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + bc.signal(); + } catch (InterruptedException e) { + e.printStackTrace(); + }finally { + lock.unlock(); + } + } + } + + public void countC(){ + while(true){ + lock.lock(); + try { + if(cnt.intValue()>threshold){ + ca.signal(); + return; + } + bc.await(); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + ca.signal(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + ConditionCount syncCount=new ConditionCount(); + new Thread(syncCount::countA).start(); + new Thread(syncCount::countB).start(); + new Thread(syncCount::countC).start(); + + syncCount.lock.lock(); + System.out.println("start..."); + syncCount.ca.signal(); + syncCount.lock.unlock(); + } +} diff --git a/src/com/xycode/countEx/CountDownLatchCount.java b/src/com/xycode/countEx/CountDownLatchCount.java new file mode 100644 index 0000000..85ad3f2 --- /dev/null +++ b/src/com/xycode/countEx/CountDownLatchCount.java @@ -0,0 +1,78 @@ +package com.xycode.countEx; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * ClassName: SyncCount + * + * @Author: xycode + * @Date: 2020/3/28 + * @Description: 使用CountDownLatch实现3个线程交替计数 + **/ +public class CountDownLatchCount { + private static final int threshold=100; + private AtomicInteger cnt=new AtomicInteger(1); + private CountDownLatch ab=new CountDownLatch(1); + private CountDownLatch bc=new CountDownLatch(1); + private CountDownLatch ca=new CountDownLatch(1); + public void countA(){ + while(true){ + try { + ca.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if(cnt.intValue()>threshold) { + ab.countDown(); + return; + } + ca=new CountDownLatch(1); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + ab.countDown(); + } + } + + public void countB(){ + while(true){ + try { + ab.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if(cnt.intValue()>threshold) { + bc.countDown(); + return; + } + ab=new CountDownLatch(1); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + bc.countDown(); + } + } + + public void countC(){ + while(true){ + try { + bc.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if(cnt.intValue()>threshold){ + ca.countDown(); + return; + } + bc=new CountDownLatch(1); + System.out.println(Thread.currentThread().getId() + ": "+cnt.getAndIncrement()); + ca.countDown(); + } + } + + public static void main(String[] args) { + CountDownLatchCount syncCount=new CountDownLatchCount(); + syncCount.ca.countDown(); + new Thread(syncCount::countA).start(); + new Thread(syncCount::countB).start(); + new Thread(syncCount::countC).start(); + + } +} diff --git a/src/com/xycode/countEx/SynchronizedCount.java b/src/com/xycode/countEx/SynchronizedCount.java new file mode 100644 index 0000000..2589f84 --- /dev/null +++ b/src/com/xycode/countEx/SynchronizedCount.java @@ -0,0 +1,74 @@ +package com.xycode.countEx; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * ClassName: SynchronizedCount + * + * @Author: xycode + * @Date: 2020/3/28 + * @Description: 使用synchronized + wait/notify实现3个线程交替计数 + **/ +public class SynchronizedCount { + private static final int threshold=123; + private volatile int state=1; + private AtomicInteger cnt=new AtomicInteger(1); + public void countA(){ + while(cnt.intValue(){ + Connection connection=pool.getConnection(); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + pool.releaseConnection(connection); + }).start(); + } + + } + + + static class MockConnection implements Connection{ + private String name; + + public MockConnection(String name) { + this.name = name; + } + + @Override + public String toString() { + return "MockConnection{" + + "name='" + name + '\'' + + '}'; + } + + @Override + public Statement createStatement() throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return null; + } + + @Override + public String nativeSQL(String sql) throws SQLException { + return null; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + } + + @Override + public boolean getAutoCommit() throws SQLException { + return false; + } + + @Override + public void commit() throws SQLException { + + } + + @Override + public void rollback() throws SQLException { + + } + + @Override + public void close() throws SQLException { + + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return null; + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + } + + @Override + public String getCatalog() throws SQLException { + return null; + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + } + + @Override + public int getTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public Map> getTypeMap() throws SQLException { + return null; + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + } + + @Override + public int getHoldability() throws SQLException { + return 0; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return null; + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return null; + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return null; + } + + @Override + public Clob createClob() throws SQLException { + return null; + } + + @Override + public Blob createBlob() throws SQLException { + return null; + } + + @Override + public NClob createNClob() throws SQLException { + return null; + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return null; + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return false; + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + } + + @Override + public String getClientInfo(String name) throws SQLException { + return null; + } + + @Override + public Properties getClientInfo() throws SQLException { + return null; + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return null; + } + + @Override + public void setSchema(String schema) throws SQLException { + + } + + @Override + public String getSchema() throws SQLException { + return null; + } + + @Override + public void abort(Executor executor) throws SQLException { + + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + + } + + @Override + public int getNetworkTimeout() throws SQLException { + return 0; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + } +} diff --git a/src/com/xycode/executor/myThreadPool/MyBlockingQueue.java b/src/com/xycode/executor/myThreadPool/MyBlockingQueue.java new file mode 100644 index 0000000..762f1bb --- /dev/null +++ b/src/com/xycode/executor/myThreadPool/MyBlockingQueue.java @@ -0,0 +1,148 @@ +package com.xycode.executor.myThreadPool; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Logger; + +/** + * ClassName: MyBlockingQueue + * + * @Author: xycode + * @Date: 2020/2/26 + * @Description: this is description of the MyBlockingQueue class + **/ +public class MyBlockingQueue { + private static final Logger logger=Logger.getLogger("MyLogger"); + private Deque queue; + private int capacity; + + private ReentrantLock lock=new ReentrantLock(); + private Condition notEmpty=lock.newCondition(); + private Condition notFull=lock.newCondition(); + + private MyRejectStrategy rejectStrategy; + + public MyBlockingQueue(int capacity) { + this.capacity = capacity; + queue=new ArrayDeque<>(capacity); + } + + public MyBlockingQueue(Deque queue, MyRejectStrategy rejectStrategy) { + this.queue = queue; + this.rejectStrategy = rejectStrategy; + } + + //带超时参数的取元素 + public T poll(long timeout, TimeUnit timeUnit){ + //时间单位统一成纳秒 + long nanos=timeUnit.toNanos(timeout); + lock.lock(); + try { + while(queue.isEmpty()){ + try { + if(nanos<=0) return null; + System.out.println("queue is empty"); + nanos=notEmpty.awaitNanos(nanos); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + T e=queue.removeFirst(); + notFull.signal(); + return e; + } finally { + lock.unlock(); + } + } + + public T take(){ + lock.lock(); + try { + while(queue.isEmpty()){ + try { + notEmpty.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //取出元素了,那肯定就不满了 + T e=queue.removeFirst(); + notFull.signal(); + return e; + } finally { + lock.unlock(); + } + } + + public void put(T element){ + lock.lock(); + try { + while(queue.size()==capacity){//满的 + try { + System.out.println("waiting for add element into queue"); + notFull.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + queue.addLast(element); + //添加元素了,那肯定就不为空了 + notEmpty.signal(); + } finally { + lock.unlock(); + } + } + + //带超时参数的添加元素 + public boolean offer(T element,long timeout,TimeUnit timeUnit){ + //时间单位统一成纳秒 + long nanos=timeUnit.toNanos(timeout); + lock.lock(); + try { + while(queue.size()==capacity){//满的 + try { + if(nanos<=0) return false; + nanos=notEmpty.awaitNanos(nanos); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + queue.addLast(element); + //添加元素了,那肯定就不为空了 + notEmpty.signal(); + return true; + } finally { + lock.unlock(); + } + } + + public int size(){ + lock.lock(); + try { + return queue.size(); + } finally { + lock.unlock(); + } + } + + public void putWithReject(MyRejectStrategy rejectStrategy,T element){ + lock.lock(); + try { + if(queue.size()==capacity){//满的 + rejectStrategy.reject(this,element); + }else{ + queue.addLast(element); + //添加元素了,那肯定就不为空了 + notEmpty.signal(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + +} diff --git a/src/com/xycode/executor/myThreadPool/MyRejectStrategy.java b/src/com/xycode/executor/myThreadPool/MyRejectStrategy.java new file mode 100644 index 0000000..e91fdf4 --- /dev/null +++ b/src/com/xycode/executor/myThreadPool/MyRejectStrategy.java @@ -0,0 +1,14 @@ +package com.xycode.executor.myThreadPool; + +/** + * InterfaceName: MyRejectStrategy + * + * @Author: xycode + * @Date: 2020/2/26 + * @Description: this is description of the interface + **/ +@FunctionalInterface +public interface MyRejectStrategy { + //拒绝策略,需要拿到任务队列与待添加的任务 + void reject(MyBlockingQueue queue,T element) throws Exception; +} diff --git a/src/com/xycode/executor/myThreadPool/MyThreadPool.java b/src/com/xycode/executor/myThreadPool/MyThreadPool.java new file mode 100644 index 0000000..d7ee5b5 --- /dev/null +++ b/src/com/xycode/executor/myThreadPool/MyThreadPool.java @@ -0,0 +1,118 @@ +package com.xycode.executor.myThreadPool; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +/** + * ClassName: MyThreadPool + * + * @Author: xycode + * @Date: 2020/2/26 + * @Description: this is description of the MyThreadPool class + **/ +public class MyThreadPool { + private static final Logger logger=Logger.getLogger("MyLogger"); + //任务队列 + private MyBlockingQueue taskQueue; + + //存放任务执行单元的容器 + private final Set workers=new HashSet<>(); + + //核心线程数 + private int coreSize; + + //任务等待的超时时间 + private long timeout; + private TimeUnit timeUnit; + + //拒绝策略 + private MyRejectStrategy rejectStrategy; + + public MyThreadPool(int coreSize, long timeout, TimeUnit timeUnit,int queueCapacity) { + this.coreSize = coreSize; + this.timeout = timeout; + this.timeUnit = timeUnit; + + this.taskQueue=new MyBlockingQueue<>(queueCapacity); + //默认拒绝策略,死等(实际上没有拒绝) + this.rejectStrategy= (queue, element) -> queue.put(element); + } + + public MyThreadPool(int coreSize, long timeout, TimeUnit timeUnit,int queueCapacity,MyRejectStrategy rejectStrategy) { + this.coreSize = coreSize; + this.timeout = timeout; + this.timeUnit = timeUnit; + + this.taskQueue=new MyBlockingQueue<>(queueCapacity); + + this.rejectStrategy=rejectStrategy; + } + + public void execute(Runnable task){ + synchronized (workers){//这里针对workers的操作非线程安全,所以加上同步 + if(workers.size() { + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("-->"+Thread.currentThread().getName()+" execute task"); + }); + } + + } + + + //执行单元,一个对Thread的封装 + class Worker extends Thread{ + private Runnable task; + + public Worker(Runnable task) { + this.task = task; + } + + @Override + public void run() { + if(task!=null) task.run(); + //执行完自己的task后,再从任务队列中取task来执行,使用take的话,实际上这里会一直阻塞住 + while ((task=taskQueue.poll(timeout,timeUnit))!=null){ + try { + task.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + synchronized (workers){ + System.out.println("remove worker"); + workers.remove(this); + } + } + } + +} + diff --git a/src/com/xycode/hashMap/TestHashMap7.java b/src/com/xycode/hashMap/TestHashMap7.java new file mode 100644 index 0000000..f9a300a --- /dev/null +++ b/src/com/xycode/hashMap/TestHashMap7.java @@ -0,0 +1,17 @@ +package com.xycode.hashMap; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; + +/** + * ClassName: TestHashMap + * + * @Author: xycode + * @Date: 2020/3/1 + * @Description: this is description of the TestHashMap class + **/ +public class TestHashMap7 { + public static void main(String[] args) { + } +} diff --git a/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java b/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java index 112604a..4a3b48b 100644 --- a/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java +++ b/src/com/xycode/synchronizedDemo/LockPromote/ObjectHeader.java @@ -1,6 +1,7 @@ package com.xycode.synchronizedDemo.LockPromote; import org.openjdk.jol.info.ClassLayout; +import org.testng.annotations.Test; import java.nio.ByteOrder; import java.util.*; @@ -21,10 +22,15 @@ static class Obj{ // byte[] array=new byte[100]; } + /** + * 获得二进制数据 + * @param o + * @return + */ public static String getObjectHeader(Object o){ ByteOrder order=ByteOrder.nativeOrder();//字节序 String table=ClassLayout.parseInstance(o).toPrintable(); - Pattern p=Pattern.compile("(0|1){8}"); + final Pattern p=Pattern.compile("(0|1){8}"); Matcher matcher=p.matcher(table); List header=new ArrayList<>(); while(matcher.find()){ @@ -43,7 +49,8 @@ public static String getObjectHeader(Object o){ /** * 针对64bit jvm的解析对象头函数 - * 在64bit jvm中,对象头有两个部分: Mark Word和Class Pointer, Mark Word占8字节,Class Pointer占4字节 + * 在64bit jvm中,对象头有两个部分: Mark Word和Class Pointer, Mark Word占8字节,Class Pointer則看具体情况4字节或8字节 + * Class Pointer占4字节(64bit JVM开启压缩指针选项(默认是开启的),不开启的话就是8个字节) * @param s 对象头的二进制形式字符串(每8位,使用一个空格分开) */ public static void parseObjectHeader(String s){ @@ -85,6 +92,49 @@ public static void parseObjectHeader(String s){ } + @Test + public void testBiasedLock(){ + //需要禁止偏向锁延迟: -XX:BiasedLockingStartupDelay=0 + Obj o=new Obj(); + parseObjectHeader(getObjectHeader(o)); + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + } + + @Test + public void testLightLock(){ + //需要禁止偏向锁延迟: -XX:BiasedLockingStartupDelay=0 + Obj o=new Obj(); + parseObjectHeader(getObjectHeader(o)); + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + //升级为轻量级锁,因为下面的线程又占用了o,注意是上面先执行完后,才开启下面这个线程,因此不会升级为重量级锁 + new Thread(()->{ + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + }).start(); + } + + @Test + public void testHeavyLock(){ + //这里没有禁止偏向锁延迟,所以最初是无锁状态 + Obj o=new Obj(); + parseObjectHeader(getObjectHeader(o)); + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + //重量级锁 + for(int i=0;i<2;++i)//线程数大于1时(交错执行),会升级成重量级锁 + new Thread(()->{ + synchronized (o){ + parseObjectHeader(getObjectHeader(o)); + } + }).start(); + } + public static void main(String[] args) { /** * Mark Word 占 8 字节 @@ -97,11 +147,11 @@ public static void main(String[] args) { * 00: 轻量级锁 * 10: 重量级锁 * - * 11: GC标记,当为该值是,偏向锁标志位必定为0 + * 11: GC标记,这种情况下,偏向锁标志位必定为0 */ Obj o=new Obj(); // 测试synchronized锁升级的情况,若要立即查看测试情况,需要禁止偏向锁延迟: -XX:BiasedLockingStartupDelay=0 -// 开启偏向锁: -XX:+UseBiasedLocking=0, jdk6开始就默认开启了,不开启就是先使用轻量级锁 +// 开启偏向锁: -XX:+UseBiasedLocking=0, jdk6开始就默认开启了,不开启的话就是先使用轻量级锁 // System.out.println(o.hashCode());//notice: 调用hashcode后就没有偏向锁了...(因为bit位置被占了) //main线程,偏向锁 diff --git a/src/com/xycode/unsafe/MyAtomicInteger.java b/src/com/xycode/unsafe/MyAtomicInteger.java new file mode 100644 index 0000000..983b7cd --- /dev/null +++ b/src/com/xycode/unsafe/MyAtomicInteger.java @@ -0,0 +1,71 @@ +package com.xycode.unsafe; + +import org.testng.annotations.Test; +import sun.misc.Unsafe; + +import java.util.concurrent.TimeUnit; + +/** + * ClassName: MyAtomicInteger + * + * @Author: xycode + * @Date: 2020/2/25 + * @Description: this is description of the MyAtomicInteger class + **/ +public class MyAtomicInteger { + private static final Unsafe UNSAFE; + + private volatile int value; + private static final long valueOffset; + + public MyAtomicInteger() { + } + + public MyAtomicInteger(int value) { + this.value = value; + } + + static{ + UNSAFE=UnsafeUtils.getUnsafe(); + try { + //设置value在类中的偏移量 + valueOffset=UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value")); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public int getValue(){ + return value; + } + + public void increment(int count){ + //while(true) + CAS实现原子操作 + while (true){ + int expectedValue=value; + int newValue=count+value; + if(UNSAFE.compareAndSwapInt(this,valueOffset,expectedValue,newValue)) break; + } + } + + public void decrement(int count){ + increment(-count); + } + + @Test + public void testMyAtomicInteger(){ + MyAtomicInteger myAtomicInteger=new MyAtomicInteger(100); + for(int i=0;i<10;++i){ + new Thread(()-> myAtomicInteger.increment(5)).start(); + new Thread(()-> myAtomicInteger.decrement(5)).start(); + } + try { + TimeUnit.SECONDS.sleep(3); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + //若线程安全的话应该会输出100 + System.out.println(myAtomicInteger.getValue());// -> 100 + } +} diff --git a/src/com/xycode/unsafe/TestUnsafe.java b/src/com/xycode/unsafe/TestUnsafe.java new file mode 100644 index 0000000..d447ad4 --- /dev/null +++ b/src/com/xycode/unsafe/TestUnsafe.java @@ -0,0 +1,52 @@ +package com.xycode.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +/** + * ClassName: TestUnsafe + * + * @Author: xycode + * @Date: 2020/2/25 + * @Description: this is description of the TestUnsafe class + **/ +public class TestUnsafe { + public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { + //通过反射方式获取Unsafe的theUnsafe域 + Field unsafeField= Unsafe.class.getDeclaredField("theUnsafe"); + System.out.println(unsafeField); + + //theUnsafe是private的,所以这里需要设置访问权限 + unsafeField.setAccessible(true); + + //根据theUnsafe获得Unsafe对象,注意这里这里的theUnsafe是static的,所以用get(null) + Unsafe unsafe= (Unsafe) unsafeField.get(null); + + //使用Unsafe的CAS操作 + Student student=new Student(); + //获取id,name在对象中的偏移量,以便后续CAS使用 + long idOffset=unsafe.objectFieldOffset(Student.class.getDeclaredField("id")); + long nameOffset=unsafe.objectFieldOffset(Student.class.getDeclaredField("name")); + unsafe.compareAndSwapInt(student,idOffset,0,1234); + unsafe.compareAndSwapObject(student,nameOffset,null,"徐岩"); + + //测试看是否赋值成功 + System.out.println(student); + } + + + static class Student{ + volatile int id; + volatile String name; + + @Override + public String toString() { + return "Student{" + + "id=" + id + + ", name=" + name + + '}'; + } + } + +} diff --git a/src/com/xycode/unsafe/UnsafeUtils.java b/src/com/xycode/unsafe/UnsafeUtils.java new file mode 100644 index 0000000..1eed990 --- /dev/null +++ b/src/com/xycode/unsafe/UnsafeUtils.java @@ -0,0 +1,33 @@ +package com.xycode.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +/** + * ClassName: UnsafeUtils + * + * @Author: xycode + * @Date: 2020/2/25 + * @Description: this is description of the UnsafeUtils class + **/ +public class UnsafeUtils { + private static final Unsafe unsafe; + static{ + //通过反射方式获取Unsafe的theUnsafe域 + try { + Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + //theUnsafe是private的,所以这里需要设置访问权限 + unsafeField.setAccessible(true); + + //根据theUnsafe获得Unsafe对象,注意这里这里的theUnsafe是static的,所以用get(null) + unsafe= (Unsafe) unsafeField.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public static Unsafe getUnsafe(){ + return unsafe; + } +}