태그 보관물: Lock

java synchronized keyword는 객체에 대한 lock 이죠??

흠..
며칠전에 회사에서 synchronized keyword로 얘기를 하다가 그냥 말았다..
메쏘드(임계영역)만 lock이 걸리는 형태로 알고 있으셔서 흠..

아래 코드를 돌려보자..
아래와 같은 메세지를 뿌려준다.. 즉, 아래 코드의 singleton 객체에 대한 락은 묵시적으로 Monitor객체를 취득하고 메쏘드를 빠져나가면 반환하는 구조로 되어 있는데 말이다..

따라서, 메쏘드 01에 진입을 하게 되면, 02는 01이 완료될때까지 대기를 하다가 01이 완료되면 02메쏘드가 불리게 되는 그런 구조이다..

print01 call
print01 진입
print02 call
print01
print02 진입
print02

package net.sjava.test.sync;

public class SyncTestMain {
   
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Thread(){
            public void run() {
                SingleTon instance = SingleTon.getInstance();
                System.out.println(“print01 call”);
                instance.print01();           
            }
        }.start();
       
        new Thread(){
            public void run() {
                SingleTon instance = SingleTon.getInstance();
                System.out.println(“print02 call”);
                instance.print02();           
            }
        }.start();
   
    }
}

package net.sjava.test.sync;

public class SingleTon {

    private static SingleTon instance = new SingleTon();
   
    private SingleTon() {
       
    }
   
    public static SingleTon getInstance() {
        return instance;
    }
   
    public synchronized void print01() {
        System.out.println(“print01 진입”);
        try {
            Thread.sleep(5000);
            System.out.println(“print01”);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
   
    public synchronized void print02() {   
        System.out.println(“print02 진입”);
        try {
            Thread.sleep(1000);
            System.out.println(“print02”);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

* reference
 – http://iilii.egloos.com/4071694

파일에 락 걸기..

try {
        File file = new File(“filename”);
        FileChannel channel = new RandomAccessFile(file, “rw”).getChannel();

        FileLock lock = channel.lock();
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        lock.release();

        channel.close();
        
}catch(Exception e){
}

Synchronized, ReentrantLock, Thread-Safe 등에 대해서..

아래내용은 http://blog.naver.com/mtorange?Redirect=Log&logNo=130014259906 에서 발췌를 하였습니다.

Reentrant Vs Thread-Safe

1. Reentrant 한 함수는 Thread-Safe하다.
2. Thread-Safe 하다고 해서 Reentrant  하다고 볼 수 없다.
Reentrant 한 함수는 다른 Thread가 재진입을 하건 Signal handler에 의해 재진입을 하건 아무 문제 없이 동작하는 함수이다. 따라서 당연히 Thread-Safe 하다.

반면 Thread-Safe한 함수는 여러 Thread가 동시에 접근할 경우 문제만 없으면 된다.
아래 함수는 Thread-Safe하다고 할 수 있지만 Reentrant하다고 볼 수 없다.

void thread_safe_function()
{
  static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
  static int context;
  pthread_mutex_lock(&mtx);
  context ++;
  pthread_mutex_unlock(&mtx);
}

아래의 내용은 http://mindwing.kr/103 에서 발췌를 하엿습니다.
synchronized 키워드 대신 java.util.concurrent.ReentrantLock 을 쓰면 다음의 잇점들이 생깁니다.

  – lock 을 얻으려는 스레드를 interrupt 시킬 수 있다.
  – lock 을 얻는데 대한 timeout 을 설정할 수 있다.
  – lock 에 2개 이상의 condition 을 설정해서 쓸 수 있다.
  – synchronized 키워드를 위해 JVM 이 사용하는 lock 기능은 하드웨어의 lock 메커니즘과 잘 매핑되지 않는 문제를 피할 수 있다.

둘 중의 무엇을 쓸 것인지는 다음 가이드를 따르면 됩니다.

  – java.util.concurrent 패키지에는 lock 기능을 제공하는 다른 클래스들이 많이 있다.
  – 데이터 구조등의 사용 목적에 따라 이들 클래스를 쓰는 것이 synchronized 키워드나 ReentrantLock 클래스를 쓰는 것보다 낫다.
  – synchronized 키워드로 잘 동작하고 있는 코드거나 그런 코드를 잘 만들 수 있다면 synchronized 키워드를 쓰는 것이 코드 수도 적고, 에러가 발생할 가능성도 낮다.
  – 여러 condition 을 설정해서 써야 한다면 ReentrantLock 클래스를 쓴다.