Java多线程synchronized同步方法详解
在Java多线程编程中,保证线程安全是一个必须面对的问题。synchronized是Java中最常用的线程同步机制之一,可以帮助我们对代码进行加锁,防止多个线程同时执行同一段代码,从而保证数据一致性。本篇攻略将详细讲解synchronized同步方法的使用方法。
什么是synchronized
synchronized是Java中的一个关键字,可以用于修饰方法或代码块,使得并发访问共享资源时保证同步。在Java中,每个对象都有一个监视器锁(也叫内部锁或对象锁),并且只有拥有这个锁的线程才能执行该对象中的synchronized方法或代码块。
synchronized方法的定义
synchronized方法是一种加锁机制,可以防止其他线程同时进入该方法,保证方法的原子性。通常来说,synchronized方法的定义方式为:
public synchronized void method() {}
这种方式将整个方法加锁,保证了方法体内的操作是互斥的,同一时间只有一个线程可以执行该方法,避免了多线程并发访问的问题。
此外,synchronized方法还可以用来修饰静态方法,其定义方式为:
public static synchronized void staticMethod() {}
synchronized方法的示例
下面通过两个示例来帮助理解synchronized方法的使用:
示例1:两个线程修改同一变量
假设有一个计数器类Counter,其中包含一个count变量和一个increment()方法,可以将count加1。现在有两个线程同时执行increment()方法,我们需要保证count这个共享变量数据一致。
public class Counter {
private int count;
public synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + ": " + count);
}
}
在这个示例中,我们定义了一个increment()方法,并用synchronized修饰,保证了对count++这种操作时的原子性,防止了多线程同时对count进行修改的问题。
我们再来定义两个线程T1和T2,同时执行Counter的increment方法:
public class Test {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
counter.increment();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "T1");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
counter.increment();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "T2");
t1.start();
t2.start();
}
}
最终的结果将依次输出T1和T2各自增加的count,交替输出:
T1: 1
T2: 2
T1: 3
T2: 4
T1: 5
T2: 6
T1: 7
T2: 8
T1: 9
T2: 10
T1: 11
T2: 12
T1: 13
T2: 14
T1: 15
T2: 16
T1: 17
T2: 18
T1: 19
T2: 20
可以看到,通过synchronized方法,我们成功地保证了count这个共享变量的数据一致性。
示例2:两个线程访问同一对象的两个不同synchronized方法
现在有一个Person类,其中包含一个账户balance变量和一个deposit方法和一个withdraw方法,分别用来向账户中存入和取出金额:
public class Person {
private int balance;
public synchronized void deposit(int money) {
balance += money;
System.out.println(Thread.currentThread().getName() + " 存入 " + money + ",当前余额为:" + balance);
}
public synchronized void withdraw(int money) {
balance -= money;
System.out.println(Thread.currentThread().getName() + " 取出 " + money + ",当前余额为:" + balance);
}
}
在这个示例中,我们将deposit()和withdraw()方法都用synchronized修饰,保证了对balance这个共享变量的访问是互斥的,从而避免了多线程并发访问的问题。
接下来,我们定义两个线程T1和T2,其中T1执行deposit()方法并存入100元,T2执行withdraw()方法并取出50元:
public class Test {
public static void main(String[] args) {
Person person = new Person();
Thread t1 = new Thread(() -> {
person.deposit(100);
}, "T1");
Thread t2 = new Thread(() -> {
person.withdraw(50);
}, "T2");
t1.start();
t2.start();
}
}
最终的输出结果为:
T1 存入 100,当前余额为:100
T2 取出 50,当前余额为:50
通过以上示例,我们成功地实现了对共享变量的同步访问,保证多线程并发访问时数据的正确性。
总结
synchronized方法是一种常用的线程同步机制,用来修饰方法或代码块,保证多线程并发访问时共享资源的正确性。在Java中,每个对象都有一个监视器锁(也叫内部锁或对象锁),并且只有拥有这个锁的线程才能执行该对象中的synchronized方法或代码块。
除了synchronized方法,还有其他的线程同步机制,如synchronized代码块、Lock等,开发者可以根据实际应用场景选择合适的线程同步方案。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程synchronized同步方法详解 - Python技术站