我有一些关于同步关键字的用法和意义的问题。
synchronized关键字有什么意义? 什么时候应该同步方法? 它在程序上和逻辑上意味着什么?
我有一些关于同步关键字的用法和意义的问题。
synchronized关键字有什么意义? 什么时候应该同步方法? 它在程序上和逻辑上意味着什么?
当前回答
同步法等效于正常方法 同步语句(使用此语句)
class A {
public synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(this) {
// all function code
}
}
}
同步静态方法等价于Synchronized语句(使用类)
class A {
public static synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(A.class) {
// all function code
}
}
}
同步语句(使用变量)
class A {
private Object lock1 = new Object();
public void methodA() {
synchronized(lock1 ) {
// all function code
}
}
}
对于同步,我们有同步方法和同步语句。然而,同步方法类似于同步语句,所以我们只需要理解同步语句。
基本上,我们会有
synchronized(object or class) { // object/class use to provides the intrinsic lock
// code
}
这里有2个想法,有助于理解同步
每个对象/类都有一个与之相关的内在锁。 当线程调用同步语句时,它会自动获取同步语句对象的内在锁,并在方法返回时释放锁。只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁=>线程安全。
= > 当线程a调用synchronized(this){// code 1} =>时,所有synchronized(this)的块代码(类内)和所有synchronized的正常方法(类内)都被锁定,因为是SAME锁。它将在线程A解锁("// code 1"完成)后执行。
此行为类似于synchronized(变量){// code 1}或synchronized(类)。
SAME LOCK =>锁(不依赖于哪个方法?或者哪些陈述?)
使用同步方法还是同步语句?
我更喜欢同步语句,因为它更易于扩展。例如,在将来,你只需要同步方法的一部分。例如,你有两个synchronized方法,它们之间没有任何关联,但是当一个线程运行一个方法时,它会阻塞另一个方法(它可以通过使用synchronized(一个变量)来防止)。
然而,应用同步方法很简单,代码看起来很简单。对于某些类,只有一个同步方法,或者类中所有同步方法彼此相关=>,我们可以使用同步方法使代码更短,更容易理解
Note
(它与同步无关,它是对象与类或非静态与静态之间的区别)。
当你使用synchronized或普通方法或synchronized(this)或synchronized(非静态变量)时,它将基于每个对象实例进行同步。 当你使用synchronized或静态方法或synchronized(类)或synchronized(静态变量)时,它将基于类进行同步
参考
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
希望能有所帮助
其他回答
同步法等效于正常方法 同步语句(使用此语句)
class A {
public synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(this) {
// all function code
}
}
}
同步静态方法等价于Synchronized语句(使用类)
class A {
public static synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(A.class) {
// all function code
}
}
}
同步语句(使用变量)
class A {
private Object lock1 = new Object();
public void methodA() {
synchronized(lock1 ) {
// all function code
}
}
}
对于同步,我们有同步方法和同步语句。然而,同步方法类似于同步语句,所以我们只需要理解同步语句。
基本上,我们会有
synchronized(object or class) { // object/class use to provides the intrinsic lock
// code
}
这里有2个想法,有助于理解同步
每个对象/类都有一个与之相关的内在锁。 当线程调用同步语句时,它会自动获取同步语句对象的内在锁,并在方法返回时释放锁。只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁=>线程安全。
= > 当线程a调用synchronized(this){// code 1} =>时,所有synchronized(this)的块代码(类内)和所有synchronized的正常方法(类内)都被锁定,因为是SAME锁。它将在线程A解锁("// code 1"完成)后执行。
此行为类似于synchronized(变量){// code 1}或synchronized(类)。
SAME LOCK =>锁(不依赖于哪个方法?或者哪些陈述?)
使用同步方法还是同步语句?
我更喜欢同步语句,因为它更易于扩展。例如,在将来,你只需要同步方法的一部分。例如,你有两个synchronized方法,它们之间没有任何关联,但是当一个线程运行一个方法时,它会阻塞另一个方法(它可以通过使用synchronized(一个变量)来防止)。
然而,应用同步方法很简单,代码看起来很简单。对于某些类,只有一个同步方法,或者类中所有同步方法彼此相关=>,我们可以使用同步方法使代码更短,更容易理解
Note
(它与同步无关,它是对象与类或非静态与静态之间的区别)。
当你使用synchronized或普通方法或synchronized(this)或synchronized(非静态变量)时,它将基于每个对象实例进行同步。 当你使用synchronized或静态方法或synchronized(类)或synchronized(静态变量)时,它将基于类进行同步
参考
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
希望能有所帮助
synchronized关键字使线程在输入方法时获得锁,以便同一时间只有一个线程可以执行该方法(对于给定的对象实例,除非它是静态方法)。
这通常被称为使类线程安全,但我认为这是一种委婉说法。虽然同步确实可以保护Vector的内部状态不被破坏,但这通常对Vector的用户没有太大帮助。
考虑一下:
if (vector.isEmpty()){
vector.add(data);
}
尽管所涉及的方法是同步的,但由于它们分别被锁定和解锁,两个不幸计时的线程可以创建具有两个元素的向量。
所以实际上,你也必须在你的应用程序代码中同步。
因为方法级同步是a)当你不需要它的时候很昂贵,b)当你需要同步的时候不够用,所以现在有了不同步的替换(Vector的情况下是ArrayList)。
最近,并发包已经发布,其中包含许多处理多线程问题的聪明实用程序。
Synchronized的意思是,如果在特定对象上使用Synchronized块,那么与单个对象关联的多个线程可以防止脏读写。为了让你更清楚,让我们举个例子:
class MyRunnable implements Runnable {
int var = 10;
@Override
public void run() {
call();
}
public void call() {
synchronized (this) {
for (int i = 0; i < 4; i++) {
var++;
System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
}
}
}
}
public class MutlipleThreadsRunnable {
public static void main(String[] args) {
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
Thread t1 = new Thread(runnable1);
t1.setName("Thread -1");
Thread t2 = new Thread(runnable2);
t2.setName("Thread -2");
Thread t3 = new Thread(runnable1);
t3.setName("Thread -3");
t1.start();
t2.start();
t3.start();
}
}
我们已经创建了两个MyRunnable类对象,runnable1与线程1和线程3共享,而runnable2仅与线程2共享。 现在,当t1和t3启动时没有使用synchronized, PFB输出表明线程1和线程3同时影响var值,而对于线程2,var有自己的内存。
Without Synchronized keyword
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -2 var value 12
Current Thread Thread -2 var value 13
Current Thread Thread -2 var value 14
Current Thread Thread -1 var value 12
Current Thread Thread -3 var value 13
Current Thread Thread -3 var value 15
Current Thread Thread -1 var value 14
Current Thread Thread -1 var value 17
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 18
使用Synchronzied,线程3在所有场景中等待线程1完成。有两个锁,一个在runnable1上,由线程1和线程3共享,另一个在runnable2上,仅由线程2共享。
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
以我的理解,同步基本上意味着编译器编写一个监视器。进入并监控。在方法周围退出。因此,它可能是线程安全的,这取决于它是如何使用的(我的意思是,你可以编写一个具有同步方法的对象,它不是线程安全的,这取决于你的类做什么)。
好了,我认为我们已经有了足够多的理论解释,所以考虑一下这段代码
public class SOP {
public static void print(String s) {
System.out.println(s+"\n");
}
}
public class TestThread extends Thread {
String name;
TheDemo theDemo;
public TestThread(String name,TheDemo theDemo) {
this.theDemo = theDemo;
this.name = name;
start();
}
@Override
public void run() {
theDemo.test(name);
}
}
public class TheDemo {
public synchronized void test(String name) {
for(int i=0;i<10;i++) {
SOP.print(name + " :: "+i);
try{
Thread.sleep(500);
} catch (Exception e) {
SOP.print(e.getMessage());
}
}
}
public static void main(String[] args) {
TheDemo theDemo = new TheDemo();
new TestThread("THREAD 1",theDemo);
new TestThread("THREAD 2",theDemo);
new TestThread("THREAD 3",theDemo);
}
}
注意:synchronized会阻塞下一个线程对test()方法的调用,只要前一个线程的执行没有完成。线程一次只能访问一个方法。如果没有同步,所有线程都可以同时访问这个方法。
当一个线程调用对象的同步方法'test'时(这里的对象是'TheDemo'类的一个实例),它获得了该对象的锁,任何新的线程都不能调用同一对象的任何同步方法,只要之前获得锁的线程没有释放锁。
当调用类的任何静态同步方法时,也会发生类似的事情。线程获得与类关联的锁(在这种情况下,该类实例的任何非静态同步方法都可以被任何线程调用,因为对象级锁仍然可用)。只要当前持有类级锁的线程没有释放类级锁,任何其他线程都不能调用类的任何静态同步方法。
输出同步
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9
输出未同步
THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9