JAvaにおけるキーワードsynchronizedの使い方とsynchronizedとvolatileの明らかな違い
3096 ワード
ブログ参照先:https://www.cnblogs.com/wl0000-03/p/5973039.html
synchronizedはJavaのキーワードであり、同期ロックである.修飾されたオブジェクトは次のとおりです.
1.修飾されたコードブロックを同期文ブロックと呼び、その作用範囲は括弧{}で囲まれたコードであり、作用するオブジェクトはこのコードブロックを呼び出すオブジェクトである.2.修飾された方法を同期方法と呼び、その作用の範囲は方法全体であり、作用するオブジェクトはこの方法を呼び出すオブジェクトである.3.静的方法を修正し、その作用範囲は静的方法全体であり、作用するオブジェクトはこのクラスのすべてのオブジェクトである.4.synchronizedの後ろに括弧で囲まれた部分で、役割主のオブジェクトがこのクラスのすべてのオブジェクトであるクラスを変更します.
オブジェクトロックのsynchronized修飾方法とコードブロックをいくつかの例のコードで見てみましょう.
上記のコードは、最初の方法ではコードブロックを同期する方法で同期され、入力されたオブジェクトインスタンスはthisであり、現在のオブジェクトであることを示している.もちろん、他のオブジェクトインスタンスを同期する必要がある場合、他のオブジェクトのインスタンスも入力できない.
2つ目の方法は、方法を修飾する方法で同期することです.最初の同期コードブロックがthisに入力されるため、2つの同期コードに必要なオブジェクトロックはすべて同じオブジェクトロックであり、次のmainメソッドでは2つのスレッドをそれぞれ開き、test 1メソッドとtest 2メソッドを呼び出すと、2つのスレッドはいずれもそのオブジェクトロックを取得する必要があり、別のスレッドは待たなければならない.実行の結果も、test 2スレッドが実行されるまでロックが解除され、test 1スレッドが実行を開始しないことがわかります.
test 2メソッドのsynchronizedキーワードを削除すると、実行結果はどうなりますか?test1 : 4 test2 : 4 test2 : 3 test1 : 3 test1 : 2 test2 : 2 test2 : 1 test1 : 1 test2 : 0 test1 : 0
上記は実行結果であり、あるスレッドがオブジェクトロックを得たが、別のスレッドが同期していないメソッドやコードにアクセスできるため、結果出力が交互に出力されることがわかります.同期を行った方法(ロック方法)と同期を行わなかった方法(一般的な方法)は互いに影響しないが,1つのスレッドが同期方法に入り,オブジェクトロックが得られたが,他のスレッドは同期していない方法(一般的な方法)にアクセスできる.
二:synchronizedとvolatileの違いVolatileの一般的な状況は変数修飾子でsychronized修飾はコードブロックまたは方法である.volatileは操作の原子性を保証できないため、複数のスレッドがi++を同時に実行すると、volatileは彼らの操作のiが同じメモリであることを保証するしかないが、汚れたデータを書き込む場合もある.ここでロックを入れるのもロックですが、synchronizedとは異なり、ロックオブジェクトが取得されていない間はスリープ状態で他のことをすることができますが、sychronizedは待機状態です.
synchronizedはJavaのキーワードであり、同期ロックである.修飾されたオブジェクトは次のとおりです.
1.修飾されたコードブロックを同期文ブロックと呼び、その作用範囲は括弧{}で囲まれたコードであり、作用するオブジェクトはこのコードブロックを呼び出すオブジェクトである.2.修飾された方法を同期方法と呼び、その作用の範囲は方法全体であり、作用するオブジェクトはこの方法を呼び出すオブジェクトである.3.静的方法を修正し、その作用範囲は静的方法全体であり、作用するオブジェクトはこのクラスのすべてのオブジェクトである.4.synchronizedの後ろに括弧で囲まれた部分で、役割主のオブジェクトがこのクラスのすべてのオブジェクトであるクラスを変更します.
オブジェクトロックのsynchronized修飾方法とコードブロックをいくつかの例のコードで見てみましょう.
public class TestSynchronized
{
public void test1()
{
synchronized(this)
{
int i = 5;
while( i-- > 0)
{
System.out.println(Thread.currentThread().getName() + " : " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
}
public synchronized void test2()
{
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 TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" );
Thread test2 = new Thread( new Runnable() { public void run() { myt2.test2(); } }, "test2" );
test1.start();;
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
上記のコードは、最初の方法ではコードブロックを同期する方法で同期され、入力されたオブジェクトインスタンスはthisであり、現在のオブジェクトであることを示している.もちろん、他のオブジェクトインスタンスを同期する必要がある場合、他のオブジェクトのインスタンスも入力できない.
2つ目の方法は、方法を修飾する方法で同期することです.最初の同期コードブロックがthisに入力されるため、2つの同期コードに必要なオブジェクトロックはすべて同じオブジェクトロックであり、次のmainメソッドでは2つのスレッドをそれぞれ開き、test 1メソッドとtest 2メソッドを呼び出すと、2つのスレッドはいずれもそのオブジェクトロックを取得する必要があり、別のスレッドは待たなければならない.実行の結果も、test 2スレッドが実行されるまでロックが解除され、test 1スレッドが実行を開始しないことがわかります.
test 2メソッドのsynchronizedキーワードを削除すると、実行結果はどうなりますか?test1 : 4 test2 : 4 test2 : 3 test1 : 3 test1 : 2 test2 : 2 test2 : 1 test1 : 1 test2 : 0 test1 : 0
上記は実行結果であり、あるスレッドがオブジェクトロックを得たが、別のスレッドが同期していないメソッドやコードにアクセスできるため、結果出力が交互に出力されることがわかります.同期を行った方法(ロック方法)と同期を行わなかった方法(一般的な方法)は互いに影響しないが,1つのスレッドが同期方法に入り,オブジェクトロックが得られたが,他のスレッドは同期していない方法(一般的な方法)にアクセスできる.
二:synchronizedとvolatileの違いVolatileの一般的な状況は変数修飾子でsychronized修飾はコードブロックまたは方法である.volatileは操作の原子性を保証できないため、複数のスレッドがi++を同時に実行すると、volatileは彼らの操作のiが同じメモリであることを保証するしかないが、汚れたデータを書き込む場合もある.ここでロックを入れるのもロックですが、synchronizedとは異なり、ロックオブジェクトが取得されていない間はスリープ状態で他のことをすることができますが、sychronizedは待機状態です.