Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 3)

javathread.jpeg

Single Threaded Execution pattern

A pattern that limits processing so that only one thread can execute at a time. The Single Threaded Execution pattern is sometimes referred to as ** Critical Section **, or ** Critical Region **.

(Code that works as intended and code that doesn't work as intended)

Character

In the Single Threaded Execution pattern, a class with the role of ** SharedResourece ** appears. The SharedResourece role has several methods, which are classified into the following two types.

--safeMethod: A method that can be called from multiple threads at the same time without any problem. --unsafeMethod: A method that must be guarded as it should not be called by multiple threads at the same time.

The Single Threaded Execution pattern guards unsafeMethad so that it can only be accessed by one thread at a time. In Java, guard is realized by making it a synchronized method. The range that needs to be operated in a single thread is called the ** critical section **.

When to use

--When accessed by multiple threads. When an instance of the SharedResource role can be accessed by multiple threads at the same time. Not needed if all threads are running completely independently, even if they are multithreaded. Such a state is said that the thread does not ** interfere **. --When the status of the SharedResource role may change. You don't need to use the Single Thread Execution pattern if there is no possibility of the state changing. The Immutable pattern (described later) corresponds to this. --When you need to stay safe. Many Java collection classes are not thread-safe. This is to enable high speed operation when it is not necessary to keep safety. Classes that are not thread-safe are specified in the API reference.

By the way, Java provides methods to make collection classes thread-safe.

--synchronizedCollection method --synchronizedList method --synchronizedMap method --synchronizedSet method --synchronizedSortedMap method --synchronizedSoretedSet method

Survivability and deadlock

** This is very important, so write it carefully. ** **

Deadlock in Single Threaded Execution occurs when all of the following conditions are met:

  1. There are multiple SharedResource roles.
  2. The thread takes the lock of one SharedResource role and goes to get the lock of another SharedResource role.
  3. The order of locking the SharedResource role is not fixed.

For example, suppose A and B eat the rice in front of them. You need both a spoon and a fork to eat. Suppose A takes a spoon and B takes a fork. At this time, A waits for B to put the fork, and B waits for A to put the spoon. Deadlock occurs. In this example

  1. There are multiple SharedResource roles, spoon and fork,
  2. Trying to get the opponent's fork while holding the spoon is trying to get another lock while holding the lock,
  3. This time, the order of spoon → fork or fork → spoon may be used, so the order of locking is not decided.

Therefore, a deadlock has occurred. In this example, try breaking either condition 1 or 2 or 3.

Try to break 1. You only need a spoon to eat. This will not cause a deadlock. Try to break 2. Stop going to get the fork while holding the spoon. If you can eat with a spoon, eat with a spoon, and when you finish eating, put the spoon down and go to get the next fork. This does not cause a deadlock. Try to break 3. Be sure to decide that you have to take a spoon and a fork in that order. Then, when A picks up the spoon, A can pick up the fork because B has to wait for the spoon to be placed (because B never picks up the fork). No deadlock occurs.

Reusability and inheritance anomalies

Even if the SharedResource role is created exactly to ensure safety, there is a risk that the safety will be destroyed by subclassing. Inheritance can cause troublesome problems in multithreaded programming. This is called ** inheritance error **.

Critical section size and performance

In general, the Single Threaded Execution pattern degrades performance.

--Reason 1: It takes time to acquire the lock --Reason 2: Because you have to wait due to a thread collision

Think about synchronized

For example, is the following code the same as the code using synchronized?

void method() {
    lock(); //Suppose there is such a method
    ...
    unlock(); //Suppose there is such a method
}

The answer is not the same. This is because the lock is not released when a return or exception handling is executed between lock () and unlock (). On the other hand, the synchronized method and the synchronized block release the lock when exiting {}, so whether you return or throw an exception in the middle, the lock is surely released. If you have a pair of methods like lock () and unlock () and you want to call unlock () no matter what happens, use ** finally **.

void method
    lock();
    try {
        ...
    } finally {
        unlock(); //Put unlock in finally
    }
}

How to use finally like this is one of the ways to realize ** Before / After pattern **.

Note the following for synchronized methods and synchronized blocks.

――What are you protecting? -Do you keep it in other places? ――Which unit should you protect? --Which instance do you want to lock?

Atomic operation

Substitutions and references of primitive type and reference type are ** atomic **. That is, if one thread makes an assignment of n = 123 and another thread makes an assignment of n = 456, n will always be 123 or 456. However, according to the Java language specification, long and double assignments and references are not atomic. In reality, many Java language processors will implement both long and double as atomic operations. With the keyword ** volatile **, the operation on that field becomes atomic.

Counting semaphore

Single Threaded Execution is a pattern in which only "only one thread" executes a certain area. ** Counting semaphore ** enables a certain area to be executed up to "up to N threads". The ** java.util.concurrent ** package provides a ** Semaphore ** class that represents a counting semaphore. Specify the number of resources (permits) in the Semaphore constructor. Allocate resources with Semaphore's ** acquire ** method and release the release with the ** release ** method. Acquire and release must always be called in pairs. Therefore, it is recommended to use finally to create the above Before / After pattern.


Relation Summary of "Design Patterns Learned in Java Language (Multithreaded Edition)" (Part 1) Summary of "Design Patterns Learned in Java Language (Multithreaded Edition)" (Part 2)

Recommended Posts

Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 10)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 3)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 9)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 6)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 4)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 5)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 2)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 1)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 11)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 12)
Summary of "Design Patterns Learned in Java Language (Multithread Edition)" (Part 8)
[Java] Summary of design patterns
A quick review of Java learned in class part4
Summary of Java language basics
A quick review of Java learned in class part3
A quick review of Java learned in class part2
I read Hiroshi Yuki "Introduction to Design Patterns Learned in Java Language" (SB Creative)
Java Design Patterns
What I learned in Java (Part 2) What are variables?
A quick review of Java learned in class
Summary of what I learned in Spring Batch
Try design patterns in C language! Memento pattern-Let's memorize the memories of the data
[Java] Basic summary of Java not covered by Progate ~ Part 1 ~
What I learned in Java (Part 3) Instruction execution statement
Summary of how to implement default arguments in Java
Summary of Java support 2018
Java design pattern summary
What I learned in Java (Part 4) Conditional branching and repetition
[Java] Basic summary of Java not covered by Progate ~ Part 2 · List ~
Road to Java Engineer Part2 What kind of language is Java?
Read design patterns in Ruby
[Java11] Stream Summary -Advantages of Stream-
[Java] Summary of regular expressions
[Java] Summary of operators (operator)
[Java] Summary of for statements
Summary of Java Math class
Implementation of gzip in java
[Java] Summary of control syntax
Implementation of tri-tree in Java
Summary of java error processing
[Java] Summary of mathematical operations
What I have learned in Java (Part 1) Java development flow and overview
Summary of ORM "uroboroSQL" that can be used in enterprise Java
[For beginners] Summary of java constructor
Summary of [Java silver study] package
Basic usage of java Optional Part 1
thread safe process in java language
AtCoder 400 points algorithm summary (Java edition)
List of members added in Java 9
Creating lexical analysis in Java 8 (Part 2)
List of types added in Java 9
Summary of object-oriented programming using Java
Implementation of like function in Java
Creating lexical analysis in Java 8 (Part 1)