synchronized入门
为什么使用synchronized
先看案例
public class SynchronizedDemo {
public static void main(String[] args) throws InterruptedException {
TaskDemo demo = new TaskDemo();
Thread taskThread = new Thread(demo);
Thread taskThread2 = new Thread(demo);
taskThread.start();
taskThread2.start();
taskThread.join();
taskThread2.join();
System.out.println(demo.count);
}
static class TaskDemo implements Runnable {
public int count = 0;
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
runTask();
}
}
public void runTask() {
count++;
}
}
}
不难看出,以上案例期望的count值为2000,但执行多次后可以发现,count会出现小于2000的情况。
这是并发编程中一个典型的原子性问题,为了解决并发编程中的各种问题,JDK提供了很多工具,synchronized就是其中之一。
synchronized的使用
作为关键字级别的锁,synchronized的加锁与解锁过程是隐式的。
格式
修饰代码块 synchronized(lockObject){}
修饰方法 synchronized methadName(){}
修饰代码块时需要显示指定锁对象,修饰方法时隐式指定锁对象。
方法为成员方法时,以当前对象为锁对象,方法为静态方法时,以当前类对象为锁对象。
使用synchronized对先前的案例优化后代码如下
同步代码块
public class SynchronizedDemo {
public static void main(String[] args) throws InterruptedException {
TaskDemo demo = new TaskDemo();
Thread taskThread = new Thread(demo);
Thread taskThread2 = new Thread(demo);
taskThread.start();
taskThread2.start();
taskThread.join();
taskThread2.join();
System.out.println(demo.count);
}
static class TaskDemo implements Runnable {
public int count = 0;
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
runTask();
}
}
public void runTask() {
synchronized (this) {
count++;
}
}
}
}
静态同步代码块
public class SynchronizedDemo {
public static void main(String[] args) throws InterruptedException {
TaskDemo demo = new TaskDemo();
Thread taskThread = new Thread(demo);
Thread taskThread2 = new Thread(demo);
taskThread.start();
taskThread2.start();
taskThread.join();
taskThread2.join();
System.out.println(demo.count);
}
static class TaskDemo implements Runnable {
public int count = 0;
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
runTask();
}
}
public void runTask() {
synchronized (TaskDemo.class) {
count++;
}
}
}
}
同步方法
public class SynchronizedDemo {
public static void main(String[] args) throws InterruptedException {
TaskDemo demo = new TaskDemo();
Thread taskThread = new Thread(demo);
Thread taskThread2 = new Thread(demo);
taskThread.start();
taskThread2.start();
taskThread.join();
taskThread2.join();
System.out.println(demo.count);
}
static class TaskDemo implements Runnable {
public int count = 0;
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
runTask();
}
}
public synchronized void runTask() {
count++;
}
}
}
修饰静态同步方法
public class SynchronizedDemo {
public static void main(String[] args) throws InterruptedException {
TaskDemo demo = new TaskDemo();
Thread taskThread = new Thread(demo);
Thread taskThread2 = new Thread(demo);
taskThread.start();
taskThread2.start();
taskThread.join();
taskThread2.join();
System.out.println(demo.count);
}
static class TaskDemo implements Runnable {
public int count = 0;
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
runTask();
}
}
public static synchronized void runTask() {
count++;
}
}
}