2012년 7월 23일 월요일

java thread runnable synchronized volatile


현업에 있다보니 쓰레드 쓸 일이 없어서 잊고 있다가 한번 제대로 정리 해 보려고
디노보 엣지(내 키보드 이름)를 잡았다

쓰레드를 예제로 배워보자. 쓰레드는 이런 것...

-----------------------------------------------------

public class HelloWorld extends Thread {

private static final double a = 0;

public void run() {
while (true) {
System.out.println("Current Count = " + a);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");

HelloWorld t1 = new HelloWorld();
try {
t1.start();

} catch (Exception e) {
// TODO: handle exception
}

}
}

---------------------------------------------------------------

걍 메인문에다가 while(true)하고 적는 거랑 뭐가 다를까...
--------------------------------------------------------------
public class HelloWorld extends Thread {

private static final double a = 0;

public void run() {
while (true) {
System.out.println("Current Count = " + a);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");

HelloWorld t1 = new HelloWorld();
HelloWorld t2 = new HelloWorld();

try {
t1.start();
t2.start();

} catch (Exception e) {
// TODO: handle exception
}

}
}
-------------------------------------------------------------

요렇게 두개 만들면 다르다.


-------------------------------------------------------------
public class HelloWorld {

private static final double a = 0;

public HelloWorld() {

IamFine t1 = new IamFine();
IamFine t2 = new IamFine();

try {
t1.start();
t2.start();
} catch (Exception e) {
// TODO: handle exception
}
}


class IamFine extends Thread {
public IamFine () {
}

public void run() {
while (true) {
System.out.println("Current Count = " + a);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");
new HelloWorld();

}
}
-----------------------------------------------------------
쓰레드 구분해서  만들려고 내부 클레스로 바꾸었다.


--------------------------------------------------
public class HelloWorld {

private static final double a = 0;

public HelloWorld() {

IamFine t1 = new IamFine("first");
IamFine t2 = new IamFine("second");

try {
t1.start();
t2.start();
} catch (Exception e) {
// TODO: handle exception
}
}


class IamFine extends Thread {
String name;

public IamFine (String name) {
this.name = name;
}

public void run() {
while (true) {
System.out.println(name + "'s Current Count = " + a);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");
new HelloWorld();

}
}
------------------------------------------------

요렇게 이름을 넣을 수 있게 만들었다.

실행을 해 보면 first랑 second가 번갈아 가면서 나오는데
순서가 정확하지 않다는 것을 알 수 있다. 그건 중요한게 아닌데
값이 깨지는 것이다. ㅠㅠ

------------------------------------------------

public class HelloWorld {

private static double a = 0;

public HelloWorld() {

IamFine t1 = new IamFine("first");
IamFine t2 = new IamFine("second");

try {
t1.start();
t2.start();
} catch (Exception e) {
// TODO: handle exception
}
}


class IamFine extends Thread {
String name;

public IamFine (String name) {
this.name = name;
}

public void run() {
while (true) {
HelloWorld.a +=0.01;
System.out.println(name + "'s Current Count = " + a);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");
new HelloWorld();

}
}

---------------------------------------------
오옷... RACE CONDITION의 정석적인 예제가 되었다.
a 값을 서로 바꾸려고 하기 때문에 조금 실행하다 보면
숫자가 틀어져 버린다.


synchronized (this) {
HelloWorld.a +=0.01;
}

요렇게 해도 마찬가지.

synchronized (java.lang.Object.class) {
HelloWorld.a +=0.01;
}

요것도 안 먹는다.


---------------------------------------------

private  static volatile double a = 0;

요렇게 바꾸어 주면 좀 낫다. 그래도 안 깨어지는 것은 아니다.

private   volatile  static double a = 0;

 혹시나 이러면 더 괜찮을까?

 똑같다.
---------------------------------------------


volatile 써도 synchronized 써도... 해결이 안된다.

--------------------------------------------
public class HelloWorld {

private  static volatile double a = 0;

public HelloWorld() {

IamFine t1 = new IamFine("first");
IamFine t2 = new IamFine("second");

try {
t1.start();
t2.start();
} catch (Exception e) {
// TODO: handle exception
}
}


class IamFine extends Thread {
String name;

public IamFine (String name) {
this.name = name;
}

public void run() {
while (true) {
synchronized (java.lang.Object.class) {
//synchronized (IamFine.class) {
a +=0.01;
System.out.println(name + "'s Current Count = " + a);
}

try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
System.out.println("Hello World.");
new HelloWorld();

}
}
-----------------------------------------
안되는 이유를 알았다... double에 +0.1 자체가 문제였다.
역시 소숫점은 쓰면 안되 ㅠㅠ

런 에이블로 한번 바꾸어 보고 배운거 정리하면.

---------------------------------------------
public class HelloWorld {

// private  static volatile int a = 0;
private  static int a = 0;

public HelloWorld() {

Thread t1 = new Thread(new IamFine("first"));
Thread t2 = new Thread(new IamFine("second"));

try {
t1.start();
t2.start();
} catch (Exception e) {
// TODO: handle exception
}
}


class IamFine implements Runnable {
String name;

public IamFine (String name) {
this.name = name;
}

public void run() {
while (true) {
synchronized (java.lang.Object.class) {
a += 1;
System.out.println(name + "'s Current Count = " + a);
}

try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

public static void main(String[] args) {
System.out.println("Hello World.");
new HelloWorld();

}
}

---------------------------------------------
이대로 하면 숫자가 겹치는 일 없이 잘된다. 결국 volatile 을 안 쓰더라도
값을 넣는 부분과 출력 부분을 synchronized (java.lang.Object.class)로 처리해 버리면 되는 것이었다.
java.lang.Orbject.class 사랑하게 될 것 같아... ㅋㅋ


댓글 없음:

댓글 쓰기

국정원의 댓글 공작을 지탄합니다.

UPBIT is a South Korean company, and people died of suicide cause of coin investment.

 UPBIT is a South Korean company, and people died of suicide cause of coin. The company helps the people who control the market price manipu...