Java是如何做到线程同步的呢?
- 在需要同步的方法的 方法签名中加上 synchronized关键字
- 使用synchronized关键字对需要进行同步的代码块进行同步
- 使用java.util.concurrent.lock包中Lock对象(JDK1.8)
1.在需要同步的方法的 方法签名中加上 synchronized关键字
public class Data {
private int mVal = 0;
public void setDate(int mVal) {
this.mVal = mVal;
}
public int getDate() {
return mVal;
}
}
public class MyThread implements Runnable{
private Data mData = new Data();
@Override//让多个线程共享一个数据
public synchronized void run() {
int tmp = mData.getDate();
++tmp;
mData.setDate(tmp);
System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(myThread);
thread.start();
}
}
}
//打印的结果
Thread-0|1
Thread-4|2
Thread-3|3
Thread-2|4
Thread-1|5
public class MyThread implements Runnable{
private Data mData = new Data();
@Override//注释了synchronized关键字后再看结果
public /*synchronized*/ void run() {
int tmp = mData.getDate();
++tmp;
mData.setDate(tmp);
System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(myThread);
thread.start();
}
}
}
//注释了synchronized关键字后
Thread-0|2
Thread-4|5
Thread-3|4
Thread-2|3
Thread-1|2
//需要注意的是,运行的结果肯定每次都是不同的,原因:线程抢占到资源的顺序
2. 使用synchronized关键字对需要进行同步的代码块进行同步 (Data类还是一样)
public class MyThread implements Runnable{
private Data mData = new Data();
@Override//使用synchronized代码块(同步块)
public void run() {
synchronized (this) {
int tmp = mData.getDate();
++tmp;
mData.setDate(tmp);
System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(myThread);
thread.start();
}
}
}
//打印的结果
Thread-0|1
Thread-4|2
Thread-3|3
Thread-2|4
Thread-1|5
3. 使用java.util.concurrent.lock包中Lock对象(JDK1.8) 【有需要的时候再补充】
synchronized使用时需要注意的一些地方:
被synchronized关键字修饰的代码块在被线程执行之前,首先要拿到被同步对象的锁,并且一个对象仅仅是只有一个锁,比如上面被synchronized代码,首先那个方法需要拿到当前对象的锁,如果当前的锁已经被其它线程拿走了,那么还没抢到锁的线程将从可运行状态转变为阻塞状态,只有当拿到锁的线程执行完同步块的代码后,就释放锁,让给别的线程的、这样就可以保证数据的完整性!
Comments | NOTHING