Javaのsynchronizedの詳細について
初めてここで開博したことを記念して~ほほほ~
Javaにおけるsynchronized(同期呼び出し)については,これまであまり理解されていなかったが,ここで詳細な研究を行う.
第一篇:
Java言語のキーワードは、メソッドまたはコードブロックを修飾するために使用される場合、同じ時点で最大1つのスレッドだけがセグメントコードを実行することを保証します.
一、2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できない.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
二、しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスする場合、別のスレッドは、object内の非synchronized(this)同期コードブロックにアクセスすることができる.
三、特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることである.
四、第三の例は、他の同期コードブロックにも同様に適用される.すなわち、objectのsynchronized(this)同期コードブロックにスレッドがアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
五、以上の規則は他の対象ロックに対しても同様に適用する.
例: 一、2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できない.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
結果: A synchronized loop 0 A synchronized loop 1 A synchronized loop 2 A synchronized loop 3 A synchronized loop 4 B synchronized loop 0 B synchronized loop 1 B synchronized loop 2 B synchronized loop 3 B synchronized loop 4
二、しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスする場合、別のスレッドは、object内の非synchronized(this)同期コードブロックにアクセスすることができる.
結果: t1 : 4 t2 : 4 t1 : 3 t2 : 3 t1 : 2 t2 : 2 t1 : 1 t2 : 1 t1 : 0 t2 : 0
三、特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることである.
結果:
t1 : 4 t1 : 3 t1 : 2 t1 : 1 t1 : 0 t2 : 4 t2 : 3 t2 : 2 t2 : 1 t2 : 0
四、第三の例は、他の同期コードブロックにも同様に適用される.すなわち、objectのsynchronized(this)同期コードブロックにスレッドがアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
結果: t1 : 4 t1 : 3 t1 : 2 t1 : 1 t1 : 0 t2 : 4 t2 : 3 t2 : 2 t2 : 1 t2 : 0
五、以上の規則は他のオブジェクトロックにも適用される.
結果:
スレッドt 1はInnerに対するオブジェクトロックを取得するが、スレッドt 2は同じInnerの非同期部分にアクセスするためである.したがって、2つのスレッドは互いに干渉しません.
t1 : Inner.m4t1()=4 t2 : Inner.m4t2()=4 t1 : Inner.m4t1()=3 t2 : Inner.m4t2()=3 t1 : Inner.m4t1()=2 t2 : Inner.m4t2()=2 t1 : Inner.m4t1()=1 t2 : Inner.m4t2()=1 t1 : Inner.m4t1()=0 t2 : Inner.m4t2()=0
結果:
スレッドt 1とt 2は、同じInnerオブジェクトのうちの2つの関係のない部分にアクセスしているが、t 1が先にInnerに対するオブジェクトロックを取得しているため、m 4 t 2()がInnerの同期方法であるため、t 2のInner.m 4 t 2()へのアクセスもブロックされる.
t1 : Inner.m4t1()=4 t1 : Inner.m4t1()=3 t1 : Inner.m4t1()=2 t1 : Inner.m4t1()=1 t1 : Inner.m4t1()=0 t2 : Inner.m4t2()=4 t2 : Inner.m4t2()=3 t2 : Inner.m4t2()=2 t2 : Inner.m4t2()=1 t2 : Inner.m4t2()=0
Javaにおけるsynchronized(同期呼び出し)については,これまであまり理解されていなかったが,ここで詳細な研究を行う.
第一篇:
Java言語のキーワードは、メソッドまたはコードブロックを修飾するために使用される場合、同じ時点で最大1つのスレッドだけがセグメントコードを実行することを保証します.
一、2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できない.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
二、しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスする場合、別のスレッドは、object内の非synchronized(this)同期コードブロックにアクセスすることができる.
三、特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることである.
四、第三の例は、他の同期コードブロックにも同様に適用される.すなわち、objectのsynchronized(this)同期コードブロックにスレッドがアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
五、以上の規則は他の対象ロックに対しても同様に適用する.
例: 一、2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できない.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
public class Thread1 implements Runnable {
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}
結果: A synchronized loop 0 A synchronized loop 1 A synchronized loop 2 A synchronized loop 3 A synchronized loop 4 B synchronized loop 0 B synchronized loop 1 B synchronized loop 2 B synchronized loop 3 B synchronized loop 4
二、しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスする場合、別のスレッドは、object内の非synchronized(this)同期コードブロックにアクセスすることができる.
public class Thread2 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2(); } }, "t2" );
t1.start();
t2.start();
}
}
結果: t1 : 4 t2 : 4 t1 : 3 t2 : 3 t1 : 2 t2 : 2 t1 : 1 t2 : 1 t1 : 0 t2 : 0
三、特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることである.
// Thread2.m4t2() :
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
結果:
t1 : 4 t1 : 3 t1 : 2 t1 : 1 t1 : 0 t2 : 4 t2 : 3 t2 : 2 t2 : 1 t2 : 0
四、第三の例は、他の同期コードブロックにも同様に適用される.すなわち、objectのsynchronized(this)同期コードブロックにスレッドがアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
// Thread2.m4t2() :
public synchronized void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
結果: t1 : 4 t1 : 3 t1 : 2 t1 : 1 t1 : 0 t2 : 4 t2 : 3 t2 : 2 t2 : 1 t2 : 0
五、以上の規則は他のオブジェクトロックにも適用される.
public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //
inner.m4t1();
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
結果:
スレッドt 1はInnerに対するオブジェクトロックを取得するが、スレッドt 2は同じInnerの非同期部分にアクセスするためである.したがって、2つのスレッドは互いに干渉しません.
t1 : Inner.m4t1()=4 t2 : Inner.m4t2()=4 t1 : Inner.m4t1()=3 t2 : Inner.m4t2()=3 t1 : Inner.m4t1()=2 t2 : Inner.m4t2()=2 t1 : Inner.m4t1()=1 t2 : Inner.m4t2()=1 t1 : Inner.m4t1()=0 t2 : Inner.m4t2()=0
Inner.m4t2() synchronized:
private synchronized void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
結果:
スレッドt 1とt 2は、同じInnerオブジェクトのうちの2つの関係のない部分にアクセスしているが、t 1が先にInnerに対するオブジェクトロックを取得しているため、m 4 t 2()がInnerの同期方法であるため、t 2のInner.m 4 t 2()へのアクセスもブロックされる.
t1 : Inner.m4t1()=4 t1 : Inner.m4t1()=3 t1 : Inner.m4t1()=2 t1 : Inner.m4t1()=1 t1 : Inner.m4t1()=0 t2 : Inner.m4t2()=4 t2 : Inner.m4t2()=3 t2 : Inner.m4t2()=2 t2 : Inner.m4t2()=1 t2 : Inner.m4t2()=0