synchronized 有二种修饰方法:
- 修饰一个方法
synchronized public void runTest{ /**/ }
- 修饰一个代码块
public void runTest{ synchronized( /*某一对象或某一类*/ ){ /* 代码块 */ } }
synchronized 的作用范围分为修饰一个类和修饰一共对象当修饰一个对象时,不同线程的同一对象调用相同代码会发生堵塞当修饰一个类时,不同线程的同一类调用相同代码会发生堵塞修饰静态方法相当于修饰类
定义一个类(用于验证 synchronized 的作用范围)
public class Test implements Runnable { public static int Count = 0; @Override public void run() { runTest(); } public void runTest() { for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
当 synchronized 修饰一个方法时
- 若方法为非静态方法,作用的范围是一个对象
不同线程的同一对象调用该方法时会发生堵塞
//调用相同的对象synchronized public void runTest() { // 修饰非静态的方法 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } }
通过以下代码调用
Test test = new Test(); Thread thread_one = new Thread( test, "Thread_ONE" ); Thread thread_two = new Thread( test, "Thread_Two" ); thread_one.start(); thread_two.start();
结果是
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
由于该调用是二个thread任务中的对象是同一个test,第一个thread任务运行时,会将第二个任务堵塞
若对象不是同一个,则不会发生堵塞
//调用二个不同的对象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start();
结果是
Thread_Two 2 Thread_ONE 1 Thread_Two 3 Thread_ONE 4 Thread_Two 5 Thread_ONE 6 Thread_Two 7 Thread_ONE 8 Thread_Two 9 Thread_ONE 10
- 当修饰的方法为静态的方法时,作用的范围是一个类,而非一个对象。
不同线程的相同类调用该方法时都会发生堵塞
//调用相同的对象 Test test = new Test(); Thread thread_one = new Thread( test, "Thread_ONE" ); Thread thread_two = new Thread( test, "Thread_Two" ); thread_one.start(); thread_two.start(); //调用二个不同的对象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start();
结果都为
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
当 synchronized 修饰一个代码块时,作用的范围看括号内的内容。若括号内为对象,则范围是一个对象;若括号内为类,则范围是一个类
- 若括号内为对象,则范围是一个对象,效果和 synchronized 修饰非静态方法一样
public void runTest() { synchronized (this) { // 括号内为一个对象 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
效果
//调用相同的对象 Test test = new Test(); Thread thread_one = new Thread( test, "Thread_ONE" ); Thread thread_two = new Thread( test, "Thread_Two" ); thread_one.start(); thread_two.start(); //发生类堵塞 //Thread_ONE 1 //Thread_ONE 2 //Thread_ONE 3 //Thread_ONE 4 //Thread_ONE 5 //Thread_Two 6 //Thread_Two 7 //Thread_Two 8 //Thread_Two 9 //Thread_Two 10 //调用二个不同的对象 Thread thread_one = new Thread(new Test(), "Thread_ONE"); Thread thread_two = new Thread(new Test(), "Thread_Two"); thread_one.start(); thread_two.start(); // 没有发生堵塞 //Thread_Two 2 //Thread_ONE 1 //Thread_Two 3 //Thread_ONE 4 //Thread_Two 5 //Thread_ONE 6 //Thread_Two 7 //Thread_ONE 8 //Thread_Two 9 //Thread_ONE 10
- 若括号内为类,则范围是一个对象,效果和 synchronized 修饰静态方法一样
public [static] void runTest() { synchronized (Test.class) { // 括号内为一个类 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } } }
二种调用都发生堵塞
Thread_ONE 1 Thread_ONE 2 Thread_ONE 3 Thread_ONE 4 Thread_ONE 5 Thread_Two 6 Thread_Two 7 Thread_Two 8 Thread_Two 9 Thread_Two 10
参考:http://tutorials.jenkov.com/java-concurrency/synchronized.html
原文地址:https://www.cnblogs.com/lkcc/p/8178963.html
时间: 2024-10-29 21:19:27