1.synchronized 作用
保证同一时刻只有一个线程执行某块代码, 以达到并发安全的效果.
package com.company;
public class SynchronizeTest2 implements Runnable {
public static SynchronizeTest2 test = new SynchronizeTest2();
static int a = 0;
@Override
public void run() {
//synchronized (this){
System.out.println("线程开始, 名称: " + Thread.currentThread().getName());
for(int j=0;j<10000;j++){
a ++;
}
System.out.println("线程结束, 名称: " + Thread.currentThread().getName());
// }
}
public static void main(String args[]) throws InterruptedException{
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.start();
t2.start();
System.out.println((t1.getState()));
System.out.println((t2.getState()));
t1.join();
t2.join();
System.out.println(a);
System.out.println("线程结束");
}
}
变量a加一分为三步, 从内存中取a原值、给a加1、存入内存, 所以当多个线程并发去给a执行自加的时候, 就会出现问题. a最后的结果就会小于预期值20000.
如果run方法中的代码块有synchronized 修饰, 则a的自加过程在同一时刻只有一个线程执行, 保证了串行执行, a最后的值就会达到预期值20000
2. synchronized 两种用法
对象锁, 包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)
类锁, synchronized修饰的静态方法或指定锁为class对象
细分为4种
1) 对象锁 -> 普通方法锁
public class SynchronizedTest3 implements Runnable{
// 普通方法锁
@Override
public void run() {
method();
}
public synchronized void method() { // 普通方法锁
System.out.println("线程开始: " + Thread.currentThread().getName());
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("线程结束: "+ Thread.currentThread().getName());
}
public static void main(String args[]) throws InterruptedException{
SynchronizedTest3 t = new SynchronizedTest3();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("线程全部结束");
}
}
2) 对象锁-> 同步代码块锁
public class SynchronizeTest2 implements Runnable {
public static SynchronizeTest2 test = new SynchronizeTest2();
static int a = 0;
@Override
public void run() {
synchronized (this){ // 代码块锁
System.out.println("线程开始, 名称: " + Thread.currentThread().getName());
for(int j=0;j<10000;j++){
a ++;
}
System.out.println("线程结束, 名称: " + Thread.currentThread().getName());
}
}
public static void main(String args[]) throws InterruptedException{
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
Thread t3 = new Thread(test);
t1.start();
t2.start();
t3.start();
System.out.println((t1.getState()));
System.out.println((t2.getState()));
System.out.println((t3.getState()));
t1.join();
t2.join();
t3.join();
System.out.println(a);
// while ( t1.isAlive() || t2.isAlive() ){
//
// }
System.out.println("线程结束");
}
}
3) 类锁-> 静态方法加锁
public class SynchronizedTest4 implements Runnable {
// 类锁 -> 静态方法加锁
static SynchronizedTest4 s1 = new SynchronizedTest4();
static SynchronizedTest4 s2 = new SynchronizedTest4();
@Override
public void run() {
method();
}
public synchronized static void method(){ // 必须是静态方法
System.out.println("线程开始:"+ Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程结束:"+ Thread.currentThread().getName());
}
public static void main(String args[]) throws InterruptedException{
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s2);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
4) 类锁-> 类对象锁
package com.company;
public class SynchronizedTest5 implements Runnable{
@Override
public void run() { // 类锁 -> class对象锁
synchronized (SynchronizedTest5.class){
System.out.println("线程开始:"+ Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程结束:"+ Thread.currentThread().getName());
}
}
public static void main(String args[]) throws InterruptedException{
SynchronizedTest5 s1 = new SynchronizedTest5();
SynchronizedTest5 s2 = new SynchronizedTest5();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s2);
t1.start();
t2.start();
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("线程全部结束");
}
}