Merge branch 'master' into master

This commit is contained in:
郑永川 2018-09-06 18:33:02 +08:00 committed by GitHub
commit f439ed1e46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 132 additions and 22 deletions

View File

@ -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;

View File

@ -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;

View File

@ -30,7 +30,7 @@
# 一、运行时数据区域
<div align="center"> <img src="../pics//c9ad2bf4-5580-4018-bce4-1b9a71804d9c.png" width="400"/> </div><br>
<div align="center"> <img src="../pics//c9ad2bf4-5580-4018-bce4-1b9a71804d9c.png" width="450"/> </div><br>
## 程序计数器
@ -40,7 +40,7 @@
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
<div align="center"> <img src="../pics//926c7438-c5e1-4b94-840a-dcb24ff1dafe.png" width="450"/> </div><br>
<div align="center"> <img src="../pics//926c7438-c5e1-4b94-840a-dcb24ff1dafe.png" width="500"/> </div><br>
可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小:

View File

@ -316,7 +316,7 @@ FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示
VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长当超出一个页所能容纳的大小时就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。
VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除
在进行存储和检索时,会保留 VARCHAR 末尾的空格,而会删除 CHAR 末尾的空格
## 时间和日期

View File

@ -1433,7 +1433,8 @@ public boolean IsPopOrder(int[] pushSequence, int[] popSequence) {
Stack<Integer> 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++;
}

View File

@ -13,8 +13,8 @@
* [经典同步问题](#经典同步问题)
* [进程通信](#进程通信)
* [三、死锁](#三死锁)
* [死锁的必要条件](#死锁的必要条件)
* [死锁的处理方法](#死锁的处理方法)
* [必要条件](#必要条件)
* [处理方法](#处理方法)
* [鸵鸟策略](#鸵鸟策略)
* [死锁检测与死锁恢复](#死锁检测与死锁恢复)
* [死锁预防](#死锁预防)
@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H
Ⅳ 通信方面
进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。
进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)
## 进程状态的切换
@ -458,6 +458,116 @@ 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).
```source-c
int readcount, writecount; //(initial value = 0)
semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
//READER
void reader() {
<ENTRY Section>
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
<CRITICAL Section>
//reading is performed
<EXIT Section>
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
void writer() {
<ENTRY Section>
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
<CRITICAL Section>
down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource
//writing is performed
up(&resource); //release file
<EXIT Section>
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 ReadLock. On the otherhand, writers doesnt 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.
```source-c
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
// <ENTER>
down(&resourceAccess); // request exclusive access to resource
// </ENTER>
up(&serviceQueue); // let next in line be serviced
// <WRITE>
writeResource(); // writing is performed
// </WRITE>
// <EXIT>
up(&resourceAccess); // release resource access for next reader/writer
// </EXIT>
}
void reader()
{
down(&serviceQueue); // wait in line to be serviced
down(&readCountAccess); // request exclusive access to readCount
// <ENTER>
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
// </ENTER>
up(&serviceQueue); // let next in line be serviced
up(&readCountAccess); // release access to readCount
// <READ>
readResource(); // reading is performed
// </READ>
down(&readCountAccess); // request exclusive access to readCount
// <EXIT>
readCount--; // update count of active readers
if (readCount == 0) // if there are no readers left:
up(&resourceAccess); // release resource access for all
// </EXIT>
up(&readCountAccess); // release access to readCount
}
```
### 2. 哲学家进餐问题
<div align="center"> <img src="../pics//a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
@ -596,7 +706,7 @@ FIFO 常用于客户-服务器应用程序中FIFO 用作汇聚点,在客户
# 三、死锁
## 死锁的必要条件
## 必要条件
<div align="center"> <img src="../pics//c037c901-7eae-4e31-a1e4-9d41329e5c3e.png"/> </div><br>
@ -605,7 +715,7 @@ FIFO 常用于客户-服务器应用程序中FIFO 用作汇聚点,在客户
- 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。
- 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。
## 死锁的处理方法
## 处理方法
主要有以下四种方法:

View File

@ -175,10 +175,6 @@ public class Singleton {
}
```
该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。
该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public然后调用构造函数从而实例化对象如果要防止这种攻击需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。
#### Ⅵ 枚举实现
使用单元素的枚举类型来实现单例模式,相对于常规的单例模式,枚举实现的单例天生具有防止反射实例化对象和反序列化产生实例化对象,而且代码更加简洁,非常适合单例模式场景下使用。以下是枚举单例模式的实现。
@ -219,10 +215,11 @@ public enum EnumSingleton {
e.printStackTrace();
}
}
}
```
```
该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。
该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public然后调用构造函数从而实例化对象如果要防止这种攻击需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。
### Examples
@ -3035,5 +3032,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)