标签:
Once I talked about Process Synchronization, and provided a demo program of Search/Insert/Delete Problem.
As a matter of fact, such Critical Section Problems have a general form: given num different types of threads, as well as all pairs of i and j such that thread type i and type j cannot get access to the critical section together (possibly i==j), describe the behavior of each type of thead so that all of them can work orderly without deadlock or starvation. Search/insert/delete problem is just a single case when num=3, there are other examples such as Reader-Writer Problem and Baboon Crossing Problem.
The input of such problem should comprise: (1) one integer num indicating the number of thread types; (2) num integers indicating the number of each type of threads; (3) one integer N indicating the number of following input pairs; (4) N integer pairs representing the thread types that cannot coexist in the critical section. For example, for the search/insert/delete problem, we assume there are 100 threads to search, 50 threads to insert and 20 threads to delete, then the input should be:
3 100 50 20 4 0 2 1 1 1 2 2 2
To such problems, thus far I have come up with a naive general solution:
1 import java.util.concurrent.atomic.*; 2 import java.util.concurrent.*; 3 import java.util.*; 4 import java.io.*; 5 6 class Input { 7 private Scanner in; 8 private StringTokenizer tok; 9 10 public Input() { 11 in = new Scanner(new BufferedInputStream(System.in)); 12 } 13 public String nextString() { 14 while (tok==null||!tok.hasMoreTokens()) { 15 tok = new StringTokenizer(in.nextLine()); 16 } 17 return tok.nextToken(); 18 } 19 public int nextInt() { 20 while (tok==null||!tok.hasMoreTokens()) { 21 tok = new StringTokenizer(in.nextLine()); 22 } 23 return Integer.parseInt(tok.nextToken()); 24 } 25 public double nextDouble() { 26 while (tok==null||!tok.hasMoreTokens()) { 27 tok = new StringTokenizer(in.nextLine()); 28 } 29 return Double.parseDouble(tok.nextToken()); 30 } 31 public void close() { 32 in.close(); 33 } 34 } 35 36 class CSP { 37 private class Task extends Thread { 38 private int type; 39 40 public Task(int type) { 41 this.type = type; 42 } 43 public void run() { 44 try { 45 sempAcquire(); 46 System.out.println("\t"+this+" is working."); 47 sempRelease(); 48 } catch (Exception e) { 49 System.err.println("TASK RUN Error: "+e); 50 } 51 } 52 private void sempAcquire() throws InterruptedException { 53 wait.acquire(); 54 if (mutex[type][type]) { 55 semp[type][type].acquire(); 56 } 57 if (cnt[type].getAndIncrement()==0){ 58 for (int i=0;i<type;i++) { 59 if (mutex[type][i]) { 60 semp[type][i].acquire(); 61 } 62 } 63 for (int i=type+1;i<num;i++) { 64 if (mutex[i][type]) { 65 semp[i][type].acquire(); 66 } 67 } 68 } 69 wait.release(); 70 } 71 private void sempRelease() { 72 if (cnt[type].getAndDecrement()==1){ 73 for (int i=num-1;i>type;i--) { 74 if (mutex[i][type]) { 75 semp[i][type].release(); 76 } 77 } 78 for (int i=type-1;i>=0;i--) { 79 if (mutex[type][i]) { 80 semp[type][i].release(); 81 } 82 } 83 } 84 if (mutex[type][type]) { 85 semp[type][type].release(); 86 } 87 } 88 public String toString() { 89 int idxVal = idx[type].getAndIncrement(); 90 return "Task "+type+" #"+idxVal; 91 } 92 } 93 94 private int num; 95 private Task[][] taskArr; 96 private AtomicInteger[] cnt; 97 private AtomicInteger[] idx; 98 private Semaphore wait; 99 private Semaphore[][] semp; 100 private boolean mutex[][]; 101 102 public CSP(int num) { 103 this.num = num; 104 taskArr = new Task[num][]; 105 cnt = new AtomicInteger[num]; 106 idx = new AtomicInteger[num]; 107 for (int i=0;i<num;i++) { 108 cnt[i] = new AtomicInteger(0); 109 idx[i] = new AtomicInteger(0); 110 } 111 try { 112 wait = new Semaphore(1); 113 semp = new Semaphore[num][]; 114 mutex = new boolean[num][]; 115 for (int i=0;i<num;i++) { 116 semp[i] = new Semaphore[i+1]; 117 mutex[i] = new boolean[i+1]; 118 } 119 } catch (Exception e) { 120 System.err.println("CSP INIT Error: "+e); 121 } 122 } 123 public void genThread(int type,int n) { 124 taskArr[type] = new Task[n]; 125 for (int i=0;i<n;i++) { 126 taskArr[type][i] = new Task(type); 127 } 128 } 129 public void setMutex(int i,int j) { 130 if (j>i) { 131 i += j; 132 j = i-j; 133 i -= j; 134 } 135 mutex[i][j] = true; 136 try { 137 semp[i][j] = new Semaphore(1); 138 } catch (Exception e) { 139 System.err.println("CSP SETMUTEX Error: "+e); 140 } 141 } 142 public void start() { 143 class Pair { 144 public int type,idx; 145 public Pair(int i,int j) { 146 type = i; 147 idx = j; 148 } 149 } 150 List<Pair> q = new LinkedList<Pair>(); 151 for (int i=0;i<num;i++) { 152 for (int j=0;j<taskArr[i].length;j++) { 153 q.add(new Pair(i,j)); 154 } 155 } 156 Collections.shuffle(q,new Random()); 157 while (!q.isEmpty()) { 158 Pair item = q.remove(0); 159 taskArr[item.type][item.idx].start(); 160 } 161 } 162 public void join() { 163 try { 164 for (int i=0;i<num;i++) { 165 for (int j=0;j<taskArr[i].length;j++) { 166 taskArr[i][j].join(); 167 } 168 } 169 } catch (Exception e) { 170 System.err.println("CSP JOIN Error: "+e); 171 } 172 } 173 } 174 175 176 public class Main { 177 178 public static void main(String[] args) { 179 Input in = new Input(); 180 int n = in.nextInt(); 181 CSP csp = new CSP(n); 182 for (int i=0;i<n;i++) { 183 csp.genThread(i,in.nextInt()); 184 } 185 int m = in.nextInt(); 186 for (int i=0;i<m;i++) { 187 csp.setMutex(in.nextInt(),in.nextInt()); 188 } 189 in.close(); 190 System.out.println("Critical Section Problem:"); 191 csp.start(); 192 csp.join(); 193 } 194 }
=======================================================
(1) Premature optimization is the root of all evil.
(2) Adding manpower to a late software project makes it later.
General Critical Section Problem
标签:
原文地址:http://www.cnblogs.com/DevinZ/p/4503585.html