From a015b110387eb4a183fac7dc9526de6cd9e316b3 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 5 Sep 2018 17:22:45 +0800 Subject: [PATCH 1/7] auto commit --- notes/Java IO.md | 3 +++ notes/Java 基础.md | 11 ++++++----- notes/Java 虚拟机.md | 4 ++-- notes/剑指 offer 题解.md | 3 ++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index ee23a4bb..acb95b36 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -182,8 +182,10 @@ public static void readFileContent(String filePath) throws IOException { ```java public static void main(String[] args) throws IOException, ClassNotFoundException { + A a1 = new A(123, "abc"); String objectFile = "file/a1"; + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile)); objectOutputStream.writeObject(a1); objectOutputStream.close(); @@ -195,6 +197,7 @@ public static void main(String[] args) throws IOException, ClassNotFoundExceptio } private static class A implements Serializable { + private int x; private String y; diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 5b689cf8..d8f17cef 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -685,26 +685,26 @@ protected void finalize() throws Throwable {} **1. 等价关系** -(一)自反性 +Ⅰ 自反性 ```java x.equals(x); // true ``` -(二)对称性 +Ⅱ 对称性 ```java x.equals(y) == y.equals(x); // true ``` -(三)传递性 +Ⅲ 传递性 ```java if (x.equals(y) && y.equals(z)) x.equals(z); // true; ``` -(四)一致性 +Ⅳ 一致性 多次调用 equals() 方法结果不变 @@ -712,7 +712,7 @@ if (x.equals(y) && y.equals(z)) x.equals(y) == x.equals(y); // true ``` -(五)与 null 的比较 +Ⅴ 与 null 的比较 对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false @@ -741,6 +741,7 @@ System.out.println(x == y); // false ```java public class EqualExample { + private int x; private int y; private int z; diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 333c1418..2ad1527c 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -30,7 +30,7 @@ # 一、运行时数据区域 -

+

## 程序计数器 @@ -40,7 +40,7 @@ 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。 -

+

可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小: diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 9d3ada1a..2c8f2822 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1433,7 +1433,8 @@ public boolean IsPopOrder(int[] pushSequence, int[] popSequence) { Stack stack = new Stack<>(); for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) { stack.push(pushSequence[pushIndex]); - while (popIndex < n && stack.peek() == popSequence[popIndex]) { + while (popIndex < n && !stack.isEmpty() + && stack.peek() == popSequence[popIndex]) { stack.pop(); popIndex++; } From 4fa8a6b8d63306c6435401fc40a30b466f8c1d04 Mon Sep 17 00:00:00 2001 From: Bandi Yugandhar Date: Wed, 5 Sep 2018 21:50:08 +0530 Subject: [PATCH 2/7] =?UTF-8?q?Update=20and=20rename=20notes/=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E6=9C=BA=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md=20to?= =?UTF-8?q?=20=20notes/=E8=AE=A1=E7=AE=97=E6=9C=BA=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4125d86d..8751d4f8 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -456,6 +456,118 @@ void writer() { up(&data_mutex); } } +``` +The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer). + + + + +```c +int readcount, writecount; //(initial value = 0) +semaphore rmutex, wmutex, readTry, resource; //(initial value = 1) + +//READER +reader() { + + down(&readLock); // reader is trying to enter + down(&rmutex); // lock to increase readcount + readcount++; + if (readcount == 1) + down(&resource); //if you are the first reader then lock the resource + up(&rmutex); //release for other readers + up(&readLock); //Done with trying to access the resource + + +//reading is performed + + + down(&rmutex); //reserve exit section - avoids race condition with readers + readcount--; //indicate you're leaving + if (readcount == 0) //checks if you are last reader leaving + up(&resource); //if last, you must release the locked resource + up(&rmutex); //release exit section for other readers +} + + +//WRITER +writer() { + + down(&wmutex); //reserve entry section for writers - avoids race conditions + writecount++; //report yourself as a writer entering + if (writecount == 1) //checks if you're first writer + down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS + up(&wmutex); //release entry section + + + down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource + //writing is performed + up(&resource); //release file + + + down(&wmutex); //reserve exit section + writecount--; //indicate you're leaving + if (writecount == 0) //checks if you're the last writer + up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading + up(&wmutex); //release exit section +} + +We can observe that every reader is forced to acquire ReadTry lock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadTry lock, it will be released only when there is writer left in the queue. + + +From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. + +int readCount; // init to 0; number of readers currently accessing resource + +// all semaphores initialised to 1 +Semaphore resourceAccess; // controls access (read/write) to the resource +Semaphore readCountAccess; // for syncing changes to shared variable readCount +Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) + +void writer() +{ + down(&serviceQueue); // wait in line to be servicexs + // + down(&resourceAccess); // request exclusive access to resource + // + up(&serviceQueue); // let next in line be serviced + + // + writeResource(); // writing is performed + // + + // + up(&resourceAccess); // release resource access for next reader/writer + // +} + + +void reader() +{ + down(&serviceQueue); // wait in line to be serviced + down(&readCountAccess); // request exclusive access to readCount + // + if (readCount == 0) // if there are no readers already reading: + down(&resourceAccess); // request resource access for readers (writers blocked) + readCount++; // update count of active readers + // + up(&serviceQueue); // let next in line be serviced + up(&readCountAccess); // release access to readCount + + // + readResource(); // reading is performed + // + + down(&readCountAccess); // request exclusive access to readCount + // + readCount--; // update count of active readers + if (readCount == 0) // if there are no readers left: + up(&resourceAccess); // release resource access for all + // + up(&readCountAccess); // release access to readCount +} + + + ``` ### 2. 哲学家进餐问题 From 4ee1497ade4f9d0fb58d2e5fed0417919a13c158 Mon Sep 17 00:00:00 2001 From: Bandi Yugandhar Date: Wed, 5 Sep 2018 22:22:22 +0530 Subject: [PATCH 3/7] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 8751d4f8..a25daa6f 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -464,10 +464,10 @@ The first case may result Writer to starve. This case favous Writers i.e no writ ```c int readcount, writecount; //(initial value = 0) -semaphore rmutex, wmutex, readTry, resource; //(initial value = 1) +semaphore rmutex, wmutex, readLock, resource; //(initial value = 1) //READER -reader() { +void reader() { down(&readLock); // reader is trying to enter down(&rmutex); // lock to increase readcount @@ -482,7 +482,7 @@ reader() { down(&rmutex); //reserve exit section - avoids race condition with readers - readcount--; //indicate you're leaving + readcount--; //indicate you're leaving if (readcount == 0) //checks if you are last reader leaving up(&resource); //if last, you must release the locked resource up(&rmutex); //release exit section for other readers @@ -490,8 +490,8 @@ reader() { //WRITER -writer() { - +void writer() { + down(&wmutex); //reserve entry section for writers - avoids race conditions writecount++; //report yourself as a writer entering if (writecount == 1) //checks if you're first writer @@ -510,12 +510,14 @@ writer() { up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading up(&wmutex); //release exit section } +``` -We can observe that every reader is forced to acquire ReadTry lock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadTry lock, it will be released only when there is writer left in the queue. +We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue. From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. +```c int readCount; // init to 0; number of readers currently accessing resource // all semaphores initialised to 1 @@ -524,7 +526,7 @@ Semaphore readCountAccess; // for syncing changes to shared variable readCo Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) void writer() -{ +{ down(&serviceQueue); // wait in line to be servicexs // down(&resourceAccess); // request exclusive access to resource @@ -542,7 +544,7 @@ void writer() void reader() -{ +{ down(&serviceQueue); // wait in line to be serviced down(&readCountAccess); // request exclusive access to readCount // From 59fda4cc63932fff2df51645a843cb2110631734 Mon Sep 17 00:00:00 2001 From: duang123 <643363707@qq.com> Date: Thu, 6 Sep 2018 09:21:14 +0800 Subject: [PATCH 4/7] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 线程间通信也要做好同步,参考自UNP卷2 p4 --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4125d86d..60465ac5 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。 +进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 ## 进程状态的切换 From 6e61d32e20aff1ad8fc477f5e5f0d4a6b06dfaf1 Mon Sep 17 00:00:00 2001 From: zixiao Date: Thu, 6 Sep 2018 11:27:22 +0800 Subject: [PATCH 5/7] the difference of new and malloc --- notes/CyC 学习交流群 问题汇总.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md index 806d48d0..521822b9 100644 --- a/notes/CyC 学习交流群 问题汇总.md +++ b/notes/CyC 学习交流群 问题汇总.md @@ -14,3 +14,21 @@ https://www.cnblogs.com/sunziying/p/6510030.html By @CyC --- +# 1. new 和 malloc 的区别 + +* 属性 +> new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持 +* 参数 +> 使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据类型信息自行计算。malloc则需要显式指出内存的尺寸。 +* 返回类型 +> new操作内存分配成功时,返回的是对象的类型指针,类型严格与对象匹配,无需类型转换,因此new是符合类型安全的操作符。而malloc内存分配成功则是返回void *,需要通过强制类型转换将void *指针转换成我们需要的类型。 +* 分配失败 +> new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败返回NULL。 +* 自定义类型 +> new会先调用operator new 函数,申请足够的内存(通常使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型的指针。delete先调用析构函数,然后调用operator delete函函数释放内存(通常底层使用free实现) +* 重载 +> C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存的起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。malloc不允许重载。 +* 内存区域 +> new 操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是c++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序内存的动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。 +* 能够直观地重新分配内存 +> malloc可以通过relloc进行内存重新分配实现内存扩充。new没有这样的直观配套设施来扩充内存。 From 1365bc4efe3ecb2e2774cbe5b71cba3ce5e810f5 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 18:13:57 +0800 Subject: [PATCH 6/7] auto commit --- notes/CyC 学习交流群 问题汇总.md | 18 ---------- notes/MySQL.md | 2 +- notes/计算机操作系统.md | 10 +++--- notes/设计模式.md | 56 +++++--------------------------- 4 files changed, 14 insertions(+), 72 deletions(-) diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md index 521822b9..806d48d0 100644 --- a/notes/CyC 学习交流群 问题汇总.md +++ b/notes/CyC 学习交流群 问题汇总.md @@ -14,21 +14,3 @@ https://www.cnblogs.com/sunziying/p/6510030.html By @CyC --- -# 1. new 和 malloc 的区别 - -* 属性 -> new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持 -* 参数 -> 使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据类型信息自行计算。malloc则需要显式指出内存的尺寸。 -* 返回类型 -> new操作内存分配成功时,返回的是对象的类型指针,类型严格与对象匹配,无需类型转换,因此new是符合类型安全的操作符。而malloc内存分配成功则是返回void *,需要通过强制类型转换将void *指针转换成我们需要的类型。 -* 分配失败 -> new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败返回NULL。 -* 自定义类型 -> new会先调用operator new 函数,申请足够的内存(通常使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型的指针。delete先调用析构函数,然后调用operator delete函函数释放内存(通常底层使用free实现) -* 重载 -> C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存的起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。malloc不允许重载。 -* 内存区域 -> new 操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是c++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序内存的动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。 -* 能够直观地重新分配内存 -> malloc可以通过relloc进行内存重新分配实现内存扩充。new没有这样的直观配套设施来扩充内存。 diff --git a/notes/MySQL.md b/notes/MySQL.md index 3922b8a6..2c5d8935 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -316,7 +316,7 @@ FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示 VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。 -VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。 +在进行存储和检索时,会保留 VARCHAR 末尾的空格,而会删除 CHAR 末尾的空格。 ## 时间和日期 diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 60465ac5..4e3d849f 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -13,8 +13,8 @@ * [经典同步问题](#经典同步问题) * [进程通信](#进程通信) * [三、死锁](#三死锁) - * [死锁的必要条件](#死锁的必要条件) - * [死锁的处理方法](#死锁的处理方法) + * [必要条件](#必要条件) + * [处理方法](#处理方法) * [鸵鸟策略](#鸵鸟策略) * [死锁检测与死锁恢复](#死锁检测与死锁恢复) * [死锁预防](#死锁预防) @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 +进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 ## 进程状态的切换 @@ -596,7 +596,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 # 三、死锁 -## 死锁的必要条件 +## 必要条件

@@ -605,7 +605,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 - 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。 - 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。 -## 死锁的处理方法 +## 处理方法 主要有以下四种方法: diff --git a/notes/设计模式.md b/notes/设计模式.md index b893599c..262fb788 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -175,56 +175,18 @@ public class Singleton { } ``` +#### Ⅵ 枚举实现 + + ```java +public enum Singleton { + INSTANCE; +} + ``` + 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 -#### Ⅵ 枚举实现 - -使用单元素的枚举类型来实现单例模式,相对于常规的单例模式,枚举实现的单例天生具有防止反射实例化对象和反序列化产生实例化对象,而且代码更加简洁,非常适合单例模式场景下使用。以下是枚举单例模式的实现。 - -```java - -public enum EnumSingleton { - INSTANCE; //单元素枚举实现单例 - - private String objName; - - public String getObjName() { - return objName; - } - - public void setObjName(String objName) { - this.objName = objName; - } - - public static void main(String[] args) { - // 单例测试 - EnumSingleton firstSingleton = EnumSingleton.INSTANCE; - firstSingleton.setObjName("firstName"); - System.out.println(firstSingleton.getObjName()); - - EnumSingleton secondSingleton = EnumSingleton.INSTANCE; - secondSingleton.setObjName("secondName"); - System.out.println(firstSingleton.getObjName()); - System.out.println(secondSingleton.getObjName()); - - // 反射获取实例测试 - try { - Constructor constructor = EnumSingleton.class.getDeclaredConstructor(); - constructor.setAccessible(true); - EnumSingleton enumSingleton = constructor.newInstance(); - System.out.println(enumSingleton.getObjName()); - } catch (Exception e) { - e.printStackTrace(); - } - - } -} - -``` - - ### Examples - Logger Classes @@ -3036,5 +2998,3 @@ public class ImageViewer { - [Design Patterns](http://www.oodesign.com/) - [Design patterns implemented in Java](http://java-design-patterns.com/) - [The breakdown of design patterns in JDK](http://www.programering.com/a/MTNxAzMwATY.html) - - From 3c08c153beb648116e72764bd60cd0c3d925a2ec Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 18:24:01 +0800 Subject: [PATCH 7/7] auto commit --- notes/计算机操作系统.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 5eee94b4..e6c462a6 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -457,12 +457,12 @@ void writer() { } } ``` + +以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。 + The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer). - - - -```c +```source-c int readcount, writecount; //(initial value = 0) semaphore rmutex, wmutex, readLock, resource; //(initial value = 1) @@ -482,13 +482,12 @@ void reader() { down(&rmutex); //reserve exit section - avoids race condition with readers - readcount--; //indicate you're leaving + readcount--; //indicate you're leaving if (readcount == 0) //checks if you are last reader leaving up(&resource); //if last, you must release the locked resource up(&rmutex); //release exit section for other readers } - //WRITER void writer() { @@ -514,10 +513,9 @@ void writer() { We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue. - From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. -```c +```source-c int readCount; // init to 0; number of readers currently accessing resource // all semaphores initialised to 1 @@ -532,17 +530,16 @@ void writer() down(&resourceAccess); // request exclusive access to resource //
up(&serviceQueue); // let next in line be serviced - + // writeResource(); // writing is performed // - + // up(&resourceAccess); // release resource access for next reader/writer // } - void reader() { down(&serviceQueue); // wait in line to be serviced @@ -554,11 +551,11 @@ void reader() //
up(&serviceQueue); // let next in line be serviced up(&readCountAccess); // release access to readCount - + // readResource(); // reading is performed // - + down(&readCountAccess); // request exclusive access to readCount // readCount--; // update count of active readers @@ -568,10 +565,9 @@ void reader() up(&readCountAccess); // release access to readCount } - - ``` + ### 2. 哲学家进餐问题