General Critical Section Problem

  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.

时间: 2024-08-27 18:10:46

General Critical Section Problem的相关文章

Critical Section Object

Critical Section  Object  From MSDN Critical Section Objects A critical section object provides synchronization similar to that provided by a mutex object, except that a critical section can be used only by the threads of a single process. Event, mut

spinlock,mutex,semaphore,critical section的作用与差别

某年深信服的笔试题,考的就是多线程的同步.简单的解释下方便记忆: 1.spinlock:自旋锁.是专为防止多处理器并发而引入的一种锁. 2.mutex:相互排斥量. 仅仅有拥有相互排斥对象的线程才有訪问公共资源的权限.保证了资源不会同一时候被多个线程訪问. 3.semaphore:信号量.同意多个线程同一时候訪问资源,限制訪问资源的最大线程数. 4.critical section:临界区. 随意时刻仅仅同意一个线程对共享资源进行訪问.

windows下使用Critical Section和Mutex实现线程同步实例

利用critical section 和 Mutex两种不同的线程同步的方法实现生产者消费者问题.生产者线程要能够对一个计数器进行增的操作,并且将其输出在控制台上,消费者线程能够对这个计数器进行减的操作,并将其输出在控制台上.两种线程都共享一个计数器. 其中增.减计数器的数我设置为1-6随机. 测试两种方法的对比,用网上整理出的一张表如下 1.使用CriticalSection 方法时,有一个临界区cs 在将临界区传递给 InitializeCriticalSection 时(或者更准确地说,是

spinlock,mutex,semaphore,critical section的作用与区别

某年深信服的笔试题,考的就是多线程的同步,简单的解释下方便记忆: 1.spinlock:自旋锁.是专为防止多处理器并发而引入的一种锁. 2.mutex:互斥量.只有拥有互斥对象的线程才有访问公共资源的权限.保证了资源不会同时被多个线程访问. 3.semaphore:信号量.允许多个线程同时访问资源,限制访问资源的最大线程数. 4.critical section:临界区.任意时刻只允许一个线程对共享资源进行访问.

critical section的用法

critical section Critical Section: 不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问.每个进程中访问临界资源的那段代码称为临界区(Critical Section). 每个进程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源).每次只准许一个进程进入临界区,进入后不允许其他进程进入.不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问. 多个进程中涉及到同一个临

spinlock,mutex,semaphore,critical section

critical section(临界区) 在任意时刻只允许一个线程对共享资源进行访问.如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开.临界区包含两个操作原语: EnterCriticalSection() 进入临界区 LeaveCriticalSection() 离开临界区. 优点:速度快.因为Critical Section不是内核对象,函数EnterCriticalSection()和LeaveCritica

【JMeter_09】JMeter逻辑控制器__临界部分控制器&lt;Critical Section Controller&gt;

临界部分控制器<Critical Section Controller> 业务逻辑: 根据锁名来控制并发,同一个锁名之下,在同一时间点只能存在一个运行中,适用于控制并发的场景 锁名类型: 锁名为空,认为每个锁为不同的锁 锁名相同,多个锁认为是同一个锁,同一个时间点只能存在一个运行中 锁名为变量,根据变量值来判断是不是属于同一个锁,变量值为相同时,则认为是同一个锁 演示脚本: Demo_临界部分控制器 原文地址:https://www.cnblogs.com/fcholy/p/10902051.

链表,配合critical section

#include <windows.h> typedef struct _Node { struct _Node *next; int data; } Node; typedef struct _List { Node *head; CRITICAL_SECTION critical_sec; } List; List *CreateList() { List *pList = (List*)malloc(sizeof(List)); pList->head = NULL; Initia

[并发并行]_[线程同步]_[pthread和win32的临界区(Critical Section)比较]

场景: 1.  在多线程程序里,临界区是最常见的同步访问共享资源的最简单的解决方案. 2. pthread是跨平台的线程模型,那么它和本地的线程模型的临界区编程有什么区别呢? 临界区: 临界区是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权.这是让若干代码能够"以原子操作方式"来使用资源的一种方法. 所谓原子(atomic)操作方式,是指这段代码知道没有别的线程要访问这个资源. 说明: 1.  MacOSX,Windows有自己的线程模型, pthread可以说是跨平台