├── src └── edu │ └── lsu │ └── cct │ └── jguard │ ├── Runnable1.java │ ├── Callable1.java │ ├── Pseudo.grd │ ├── Two.grd │ ├── Pseudo.java │ ├── GuardWatcher.java │ ├── Pass.java │ ├── Two.java │ ├── Future.java │ ├── GuardNotWorking.java │ └── Guard.java └── README.md /src/edu/lsu/cct/jguard/Runnable1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | /** 9 | * 10 | * @author sbrandt 11 | */ 12 | public interface Runnable1 { 13 | void run(T data); 14 | } 15 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Callable1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | /** 9 | * 10 | * @author sbrandt 11 | */ 12 | public interface Callable1 { 13 | R call(A arg) throws Exception; 14 | } 15 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Pseudo.grd: -------------------------------------------------------------------------------- 1 | // implicit import 2 | // import guardian.lang.Guard; 3 | // import guardian.lang.Future; 4 | 5 | class Pseudo { 6 | static int counter; 7 | 8 | void incr() { 9 | counter++; 10 | } 11 | 12 | static Guard g = new Guard(); 13 | static GuardWatcher f = new GuardWatcher(); 14 | 15 | public static void main(String[] args) { 16 | final int N = 10000; 17 | 18 | for(int i=0;i f; 20 | } 21 | 22 | await f 23 | System.out.println("counter="+counter); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Two.grd: -------------------------------------------------------------------------------- 1 | class Two { 2 | static Guard a = new Guard(); 3 | static Guard b = new Guard(); 4 | public static void main(String[] args) { 5 | 6 | Future fn1 = guarded a { 7 | // Note: guard a is held here 8 | int inner = guarded b { 9 | // Note: guard a is not held here 10 | return 3; 11 | }; 12 | // Note: guard a is held here 13 | await inner 14 | return 4 + inner; 15 | }; 16 | 17 | Future fn2 = guarded b { 18 | int inner = guarded a { 19 | return 4; 20 | }; 21 | await inner 22 | return 3 + inner; 23 | }; 24 | 25 | await fn1 -> n1, fn2 -> n2; 26 | System.out.println(n1+n2); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JMutex 2 | 3 | In the future, this will be a revolutionary programming idea. Right now, it barely works and isn't documented. Please come back later. 4 | 5 | For GuardWatchers: GuardWatchers are used when you want to keep track of when one or more blocks of guarded code have finished. 6 | 7 | ``` 8 | Guard a,b; 9 | GuardWatcher gw; 10 | 11 | guarded a { 12 | // do stuff 13 | } -> gw; 14 | 15 | guarded b { 16 | // do more stuff 17 | } -> gw; 18 | 19 | await gw; 20 | 21 | System.out.println("All done!"); 22 | ``` 23 | 24 | When values are returned from guarded regions, they come back as futures. To get 25 | at those values, an await is needed. 26 | ``` 27 | Future f = guarded a { 28 | return 3; 29 | }; 30 | 31 | await f -> f_; // the type of f_ is "int" 32 | 33 | System.out.println("f="+f_); 34 | 35 | Future add = guarded a { 36 | Future v1 = guarded b { 37 | return 2; 38 | }; 39 | Future v2 = guarded c { 40 | return 3; 41 | } 42 | await v1 -> v1_, v2 -> v2_; 43 | return v1_ + v2_; 44 | } 45 | 46 | await add -> add_; 47 | 48 | System.out.println("add = "+add_); 49 | ``` 50 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Pseudo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * 14 | * @author sbrandt 15 | */ 16 | public class Pseudo { 17 | volatile static int counter; 18 | 19 | static void incr() { 20 | counter++; 21 | } 22 | 23 | static Guard g = new Guard(); 24 | static GuardWatcher f = new GuardWatcher(); 25 | 26 | public static void main(String[] args) { 27 | GuardWatcher f = new GuardWatcher(); 28 | 29 | final int N = 10000; 30 | 31 | for(int i=0;i f; 33 | Guard.runGuarded(g, ()->{ incr(); },f); 34 | } 35 | 36 | // await f 37 | f.await(()->{ 38 | System.out.println("counter="+counter); 39 | }); 40 | 41 | Guard.POOL.awaitQuiescence(1, TimeUnit.DAYS); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/GuardWatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.Set; 9 | 10 | /** 11 | * 12 | * @author sbrandt 13 | */ 14 | public class GuardWatcher { 15 | int count; 16 | public synchronized void incr() { 17 | count++; 18 | } 19 | public synchronized void decr() { 20 | count--; 21 | if(count == 0) 22 | notifyAll(); 23 | } 24 | private synchronized void await() { 25 | while(count > 0) { 26 | try { 27 | wait(); 28 | } catch (InterruptedException ex) { 29 | } 30 | } 31 | } 32 | 33 | public static void await(Set gset, Runnable r) { 34 | Guard.POOL.execute(() -> { 35 | for (GuardWatcher gw : gset) { 36 | gw.await(); 37 | } 38 | r.run(); 39 | }); 40 | } 41 | 42 | public void await(Runnable r) { 43 | Guard.POOL.execute(() -> { 44 | await(); 45 | try { 46 | r.run(); 47 | } catch(Exception ex) { 48 | ex.printStackTrace(); 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Pass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * 12 | * @author sbrandt 13 | */ 14 | public class Pass { 15 | 16 | static Guard a = new Guard(); 17 | static Guard b = new Guard(); 18 | 19 | public static Future add() { 20 | // int f1 = guarded a { return 3; } 21 | Future f1 = new Future<>(); 22 | Guard.runGuarded(a, f1.run(() -> { 23 | return 3; 24 | })); 25 | // int f2 = guarded b { return 4; } 26 | Future f2 = new Future<>(); 27 | Guard.runGuarded(b, f2.run(() -> { 28 | return 4; 29 | })); 30 | // await f1, f2; 31 | return f1.thenFut((Integer f1_)->{ 32 | return f2.then((Integer f2_)->{ 33 | // return f1 + f2; 34 | return f1_+f2_; 35 | }); 36 | }); 37 | } 38 | 39 | public static void main(String[] args) { 40 | // int r = add(); 41 | Future r = add(); 42 | // await r 43 | r.then((Integer r_)->{ 44 | // System.out.println("r="+r); 45 | System.out.println("r="+r_); 46 | }); 47 | Guard.POOL.awaitQuiescence(1, TimeUnit.DAYS); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Two.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | import java.util.concurrent.Callable; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.logging.Level; 13 | import java.util.logging.Logger; 14 | 15 | /** 16 | * 17 | * @author sbrandt 18 | */ 19 | public class Two { 20 | 21 | static Guard a = new Guard(); 22 | static Guard b = new Guard(); 23 | 24 | public static void main(String[] args) { 25 | // int n1 = guarded a { 26 | // int inner = guarded b { 27 | // return 3; 28 | // }; 29 | // await inner -> inner_ 30 | // return 4 + inner_; 31 | // }; 32 | 33 | Callable> n1c = ()->{ 34 | Callable c = ()->{ 35 | return 3; 36 | }; 37 | Future inner = new Future<>(); 38 | Guard.runGuarded(b,inner.run(c)); 39 | 40 | // await inner 41 | return inner.then((Integer inner_)->{ 42 | return 4 + inner_; 43 | }); 44 | }; 45 | Future n1 = new Future<>(); 46 | Guard.runGuarded(a,n1.runFut(n1c),n1.watcher); 47 | 48 | // Guard.runGuarded(a, c1, n1, _f_local_set); 49 | // 50 | // int n2 = guarded b { 51 | // int inner = guarded a { 52 | // return 4; 53 | // }; 54 | // await inner -> inner_ 55 | // return 3 + inner_; 56 | // }; 57 | 58 | Callable> n2c = ()->{ 59 | Callable c = ()->{ 60 | return 4; 61 | }; 62 | Future inner = new Future<>(); 63 | Guard.runGuarded(a,inner.run(c)); 64 | 65 | return inner.then((Integer inner_)->{ 66 | return inner_ + 3; 67 | }); 68 | }; 69 | Future n2 = new Future<>(); 70 | Guard.runGuarded(b,n2.runFut(n2c),n2.watcher); 71 | 72 | // await n1 -> n1_, n2 -> n2_; 73 | n1.then((Integer n1_)->{ 74 | n2.then((Integer n2_)->{ 75 | // System.out.println(n1 + n2); 76 | System.out.println(n1_+n2_); 77 | }); 78 | }); 79 | Guard.POOL.awaitQuiescence(1, TimeUnit.DAYS); 80 | } 81 | 82 | static void delay() { 83 | try { 84 | Thread.sleep(100); 85 | } catch (InterruptedException ex) { 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Future.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.concurrent.Callable; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.logging.Level; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * 15 | * @author sbrandt 16 | */ 17 | public class Future { 18 | private volatile T data; 19 | private volatile Exception ex;// = new Exception("Not set"); 20 | 21 | void set(T data) { 22 | ex = null; 23 | this.data = data; 24 | } 25 | void setEx(Exception ex) { 26 | this.ex = ex; 27 | this.data = null; 28 | } 29 | GuardWatcher watcher = new GuardWatcher(); 30 | 31 | public void then(Runnable1 r) { 32 | watcher.await(()->{ 33 | if(ex == null) 34 | r.run(data); 35 | else 36 | throw new RuntimeException(ex); 37 | }); 38 | } 39 | 40 | public Future then(Callable1 c) { 41 | Future f = new Future<>(); 42 | f.watcher.incr(); 43 | watcher.await(()->{ 44 | try { 45 | f.set(c.call(data)); 46 | } catch (Exception ex) { 47 | f.setEx(ex); 48 | } finally { 49 | f.watcher.decr(); 50 | } 51 | }); 52 | return f; 53 | } 54 | 55 | public void setFut(Future fut) { 56 | fut.then((T value)->{ 57 | set(value); 58 | watcher.decr(); 59 | }); 60 | } 61 | public Future thenFut(Callable1> c) { 62 | Future f = new Future<>(); 63 | f.watcher.incr(); 64 | watcher.await(()->{ 65 | try { 66 | f.setFut(c.call(data)); 67 | } catch (Exception ex) { 68 | f.setEx(ex); 69 | f.watcher.decr(); 70 | } 71 | }); 72 | return f; 73 | } 74 | 75 | public Runnable run(Callable c) { 76 | watcher.incr(); 77 | return () -> { 78 | try { 79 | set(c.call()); 80 | } catch (Exception ex) { 81 | setEx(ex); 82 | } finally { 83 | watcher.decr(); 84 | } 85 | }; 86 | } 87 | 88 | public Runnable runFut(Callable> c) { 89 | watcher.incr(); 90 | return ()->{ 91 | try { 92 | Future f = c.call(); 93 | f.watcher.await(()->{ 94 | this.data = f.data; 95 | this.ex = f.ex; 96 | watcher.decr(); 97 | }); 98 | } catch (Exception ex) { 99 | this.ex = ex; 100 | watcher.decr(); 101 | } 102 | }; 103 | } 104 | 105 | public static void main(String[] args) { 106 | Guard g = new Guard(); 107 | Future f1 = new Future<>(); 108 | Runnable r = f1.run(()->{ 109 | return 3; 110 | }); 111 | Guard.runGuarded(g, r); 112 | f1.then((Integer v)->{ 113 | System.out.println("v="+v); 114 | }); 115 | Guard.POOL.awaitQuiescence(1, TimeUnit.DAYS); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/GuardNotWorking.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.ArrayList; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | import java.util.TreeSet; 12 | import java.util.concurrent.ForkJoinPool; 13 | import java.util.concurrent.TimeUnit; 14 | import java.util.concurrent.atomic.AtomicInteger; 15 | import java.util.concurrent.locks.Lock; 16 | import java.util.concurrent.locks.ReentrantLock; 17 | 18 | /** 19 | * 20 | * @author sbrandt 21 | */ 22 | public class GuardNotWorking implements Comparable { 23 | final static AtomicInteger seq = new AtomicInteger(); 24 | final int id = seq.getAndIncrement(); 25 | 26 | public final static ForkJoinPool POOL = new ForkJoinPool(3); 27 | 28 | Lock lock = new ReentrantLock(); 29 | boolean is_running; 30 | LinkedList waiting = new LinkedList<>(); 31 | 32 | public static void runGuarded(GuardNotWorking g, Runnable r) { 33 | runGuarded(g, r, true); 34 | } 35 | 36 | private boolean lock(Runnable r) { 37 | try { 38 | lock.lock(); 39 | if (is_running) { 40 | waiting.addLast(r); 41 | return false; 42 | } 43 | assert waiting.size()==0; 44 | is_running = true; 45 | } finally { 46 | lock.unlock(); 47 | } 48 | return true; 49 | } 50 | 51 | private void unlock() { 52 | assert is_running; 53 | Runnable r = null; 54 | while (true) { 55 | try { 56 | lock.lock(); 57 | if (waiting.size() == 0) { 58 | is_running = false; 59 | return; 60 | } else { 61 | r = waiting.removeFirst(); 62 | } 63 | } finally { 64 | lock.unlock(); 65 | } 66 | r.run(); 67 | } 68 | } 69 | 70 | static void runGuarded(GuardNotWorking g, Runnable r, boolean unlock) { 71 | if (g.lock(r)) { 72 | r.run(); 73 | if (unlock) { 74 | g.unlock(); 75 | } 76 | } 77 | } 78 | 79 | public static void runGuarded(TreeSet gs, Runnable r) { 80 | List guards = new ArrayList<>(); 81 | guards.addAll(gs); 82 | runGuarded(0, guards, r); 83 | } 84 | 85 | static void runGuarded(int index, List guards, Runnable r) { 86 | if (index + 1 == guards.size()) { 87 | runGuarded(guards.get(index), () -> { 88 | r.run(); 89 | for (int i = 0; i < guards.size(); i++) { 90 | guards.get(i).unlock(); 91 | } 92 | }, false); 93 | } else { 94 | assert guards.get(index).id < guards.get(index+1).id; 95 | runGuarded(guards.get(index), () -> { 96 | runGuarded(index + 1, guards, r); 97 | }, false); 98 | } 99 | } 100 | 101 | @Override 102 | public int compareTo(GuardNotWorking that) { 103 | return this.id - that.id; 104 | } 105 | 106 | static int counter = 0, counter1 = 0, counter2 = 0; 107 | 108 | public static void main(String[] args) throws InterruptedException { 109 | try { 110 | assert false; 111 | throw new Error("Enable assertions"); 112 | } catch (AssertionError ae) { 113 | } 114 | GuardNotWorking g = new GuardNotWorking(); 115 | final int N = 10000; 116 | 117 | for (int i = 0; i < N; i++) { 118 | POOL.submit(() -> { 119 | runGuarded(g, () -> { 120 | counter++; 121 | }); 122 | }); 123 | } 124 | POOL.awaitQuiescence(1, TimeUnit.DAYS); 125 | assert N == counter; 126 | 127 | GuardNotWorking g1 = new GuardNotWorking(); 128 | GuardNotWorking g2 = new GuardNotWorking(); 129 | counter1 = counter2 = 0; 130 | TreeSet gs = new TreeSet<>(); 131 | gs.add(g1); 132 | gs.add(g2); 133 | for (int i = 0; i < N; i++) { 134 | // POOL.submit(()->{ 135 | // runGuarded(g1,()->{ 136 | // counter1++; 137 | // }); 138 | // }); 139 | // POOL.submit(()->{ 140 | // runGuarded(g2,()->{ 141 | // counter2++; 142 | // }); 143 | // }); 144 | POOL.submit(() -> { 145 | runGuarded(gs, () -> { 146 | counter1++; 147 | counter2++; 148 | }); 149 | }); 150 | } 151 | POOL.awaitQuiescence(1, TimeUnit.DAYS); 152 | Thread.sleep(1); 153 | System.out.println("counter1=" + counter1 + " counter2=" + counter2); 154 | assert N == counter1; 155 | assert N == counter2; 156 | 157 | System.out.println("done"); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/jguard/Guard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.jguard; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.TreeSet; 12 | import java.util.concurrent.Callable; 13 | import java.util.concurrent.ForkJoinPool; 14 | import java.util.concurrent.TimeUnit; 15 | import java.util.concurrent.atomic.AtomicInteger; 16 | import java.util.concurrent.locks.Lock; 17 | import java.util.concurrent.locks.ReentrantLock; 18 | import java.util.logging.Level; 19 | import java.util.logging.Logger; 20 | 21 | /** 22 | * 23 | * @author sbrandt 24 | */ 25 | public class Guard implements Comparable { 26 | 27 | final static AtomicInteger seq = new AtomicInteger(); 28 | final int id = seq.getAndIncrement(); 29 | public final static ForkJoinPool POOL = new ForkJoinPool(3); 30 | 31 | Lock lock = new ReentrantLock(); 32 | 33 | public static void runGuarded(Guard g, Runnable r) { 34 | GuardWatcher gw = null; 35 | runGuarded(g, r, gw); 36 | } 37 | 38 | public static void runGuarded(Guard g, Runnable r, GuardWatcher gw) { 39 | if(gw != null) { 40 | gw.incr(); 41 | } 42 | Runnable task = new Runnable() { 43 | @Override 44 | public void run() { 45 | try { 46 | g.lock.lock(); 47 | r.run(); 48 | } finally { 49 | g.lock.unlock(); 50 | } 51 | if (gw != null) { 52 | gw.decr(); 53 | } 54 | } 55 | }; 56 | POOL.execute(task); 57 | } 58 | public static void runGuarded(Guard g, Runnable r, Set fs) { 59 | if (fs != null) { 60 | for (GuardWatcher f : fs) { 61 | f.incr(); 62 | } 63 | } 64 | Runnable task = new Runnable() { 65 | @Override 66 | public void run() { 67 | try { 68 | g.lock.lock(); 69 | r.run(); 70 | } finally { 71 | g.lock.unlock(); 72 | } 73 | if (fs != null) { 74 | for (GuardWatcher f : fs) { 75 | f.decr(); 76 | } 77 | } 78 | } 79 | }; 80 | POOL.execute(task); 81 | } 82 | 83 | public static void runGuarded(TreeSet gs, Runnable r) { 84 | runGuarded(gs, r, null); 85 | } 86 | 87 | public static void runGuarded(TreeSet gs, Runnable r, Set fs) { 88 | if (fs != null) { 89 | for (GuardWatcher f : fs) { 90 | f.incr(); 91 | } 92 | } 93 | Runnable task = new Runnable() { 94 | @Override 95 | public void run() { 96 | try { 97 | for (Guard g : gs) { 98 | g.lock.lock(); 99 | } 100 | r.run(); 101 | } finally { 102 | for (Guard g : gs) { 103 | g.lock.unlock(); 104 | } 105 | if (fs != null) { 106 | for (GuardWatcher f : fs) { 107 | f.decr(); 108 | } 109 | } 110 | } 111 | } 112 | }; 113 | POOL.execute(task); 114 | } 115 | 116 | @Override 117 | public int compareTo(Guard that) { 118 | return this.id - that.id; 119 | } 120 | 121 | static int counter = 0, counter1 = 0, counter2 = 0; 122 | 123 | public static void main(String[] args) throws InterruptedException { 124 | try { 125 | assert false; 126 | throw new Error("Enable assertions"); 127 | } catch (AssertionError ae) { 128 | } 129 | Guard g = new Guard(); 130 | final int N = 10000; 131 | 132 | for (int i = 0; i < N; i++) { 133 | POOL.submit(() -> { 134 | runGuarded(g, () -> { 135 | counter++; 136 | }); 137 | }); 138 | } 139 | POOL.awaitQuiescence(1, TimeUnit.DAYS); 140 | assert N == counter; 141 | 142 | Guard g1 = new Guard(); 143 | Guard g2 = new Guard(); 144 | TreeSet gs = new TreeSet<>(); 145 | gs.add(g1); 146 | gs.add(g2); 147 | counter1 = counter2 = 0; 148 | for (int i = 0; i < N; i++) { 149 | POOL.submit(() -> { 150 | runGuarded(gs, () -> { 151 | counter1++; 152 | counter2++; 153 | }); 154 | }); 155 | } 156 | POOL.awaitQuiescence(1, TimeUnit.DAYS); 157 | Thread.sleep(1); 158 | System.out.println("counter1=" + counter1 + " counter2=" + counter2); 159 | assert N == counter1; 160 | assert N == counter2; 161 | 162 | counter1 = counter2 = 0; 163 | for (int i = 0; i < N; i++) { 164 | POOL.submit(() -> { 165 | runGuarded(g1, () -> { 166 | counter1++; 167 | }); 168 | }); 169 | POOL.submit(() -> { 170 | runGuarded(g2, () -> { 171 | counter2++; 172 | }); 173 | }); 174 | POOL.submit(() -> { 175 | runGuarded(gs, () -> { 176 | counter1++; 177 | counter2++; 178 | }); 179 | }); 180 | } 181 | POOL.awaitQuiescence(1, TimeUnit.DAYS); 182 | Thread.sleep(1); 183 | System.out.println("counter1=" + counter1 + " counter2=" + counter2); 184 | assert 2 * N == counter1; 185 | assert 2 * N == counter2; 186 | 187 | System.out.println("done"); 188 | } 189 | } 190 | --------------------------------------------------------------------------------