Java에서 thread를 만드는 방법은 두 가지이다.
Runnable
InterfaceThread
Class
두 방식 모두 Thread
클래스 인스턴스를 생성하여 start()
메소드를 실행해야 실제 thread가 실행되는 것이다.
public class Sample implements Runnable {
@Override
public void run(){
...
}
}
void somewhere(){
// Use class implements Runnable
Thread thread = new Thread(new Sample());
thread.start();
// Use lambda
Thread lambdaThread = new Thread(() -> {...});
lambdaThread.start();
}
Runnable
인터페이스를 이용하여 thread를 실행할 수 있다. 어떤 클래스든 인터페이스를 구현하기만 하면 언제든지 Thread
에 주입하여 새로운 thread에서 실행할 수 있다.
@Data
public class Sample extends Thread {
@Override
public void run(){
...
}
}
void somewhere(){
Sample thread = new Sample();
// Thread를 상속받았기에 바로 해당 인스턴스의 start 메소드 call
thread.start();
}
Thread
클래스도 Runnable
인터페이스를 상속받고 있다. 따라서 Thread
클래스를 상속받아 thread를 실행할 수 있는데, Thread
클래스를 상속받아 구현하는 것은 다른 클래스를 상속받아 사용할 수 없기에 권장하지 않는다.
Multi thread를 다루다 보면, thread들이 동시에 하나의 리소스에 접근하는 경우가 있다. C++에서는 mutex
lock
같은 것으로 제어한다면, Java에서는 synchronized
키워드를 사용한다.
메소드나, 블럭을 생성해서 synchronized 키워드를 사용하여 리소스 접근을 제한할 수 있다.
// 아래 두 메소드는 같은 의미의 코드이다
public synchronized void example() {
//Do something
}
public void example() {
synchronized(this) {
//Do something
}
}
// 또는 위의 this대신 다른 object를 명시해서 해당 object에 lock을 걸 수도 있다
public void example(){
synchronized(object){
//Do something
}
}
static
인 경우 살짝 차이가 있는데, 위와 같이 인스턴스가 아닌 클래스 자체에 lock을 건다.
하지만 synchronized
키워드는 성능 저하가 큰 단점이다. 그리고 static
과 인스턴스 사이의 lock은 대상이 달라 디버깅이 어려워질 여지가 있다.
성능이 좋지 않은 synchronized
대신에 무엇을 쓰면 좋을까? Lock-free가 대안 중 하나이다.
Lock-free - A data structure provides lock-freedom if, at any time, at least one thread can proceed
즉 최소한 한 스레드는 항상 작업을 진행할 수 있다면 lock-free이다. Java에서 CAS(compare-and-swap, Non-blocking 으로 동작)을 통하여 lock-free를 구현할 수 있다.
Java atimic 패키지를 통하여 CAS를 사용할 수 있으며, Java concurrent 패키지의 클래스 대부분의 구현에 atomic 패키지의 클래스가 사용되었다.
멀티 스레드 환경에서 성능 이슈가 있을 수 있으니, 따로 synchronized 키워드로 직접 컨트롤하지말고 new로 인스턴스를 새로 만들어서 해결하거나 Concurrent를 지원하는 패키지를 사용하자는 것이다.
Lock-Freedom의 3가지 수준
Wait-Free
항상 어떤 스레드도 Wait을 하지 않고 모든 쓰레드가 실행 중이며, 즉 바운더리가 있는 CPU 사이클 내에 어떤 작업이 완료될 것이라고 보장된다.Lock-Free
항상 적어도 하나의 쓰레드가 실행 중임을 보장받는다. 모든 Wait-Free는 Lock-Free이지만 반대는 성립하지않는다.Obstruction-Free
가장 약한 정의로 적어도 하나의 쓰레드가 언젠가는 방해받지 않고 고립된 상태로 실행될 것이라 보장한다.
https://coding-start.tistory.com/68
https://reference-m1.tistory.com/87
https://tourspace.tistory.com/54
https://tourspace.tistory.com/55
https://effectivesquid.tistory.com/62
https://www.baeldung.com/lock-free-programming
https://narakit.tistory.com/194