synchronized的几种用法和效果

本文深入解析Java中synchronized关键字的三种使用方式,包括实例方法、静态方法及代码块的同步控制,通过具体示例阐述不同场景下锁的作用范围及其对线程安全的影响。

---------------------------------------------------------------------------------------------------------------------------------------------

synchronized关键字的几种用法和实例:

    加在实例方法(类的某个方法上),作用于当前【实例】加锁,进入同步代码前要获得【当前实例】的锁

    加在静态方法(某个类的静态方法上),作用于当前【类对象】加锁,进入同步代码前要获得【当前类对象】的锁

    加在代码块(某个方法的一块代码上),【指定加锁对象】,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

1. 加在实例方法(类的某个方法上),作用于当前【实例】加锁,进入同步代码前要获得【当前实例】的锁
        不同的对象是锁不住的。
         效果如:com.test.synchronize.three
          com.test.synchronize.two
          com.test.synchronize.one

package com.test.synchronize.two;


public class CountTest{
	static int i=0;
	/**
	 * 方法上面加了锁定,结果任然计算不对
	 * @return
	 */
	public synchronized int add(){
		try {
			Thread.sleep(100L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        i++;
        
        return i;
    }

}
package com.test.synchronize.two;

public class ThreedOne implements Runnable{

	@Override
	public void run() {
		for(int j=0;j<10;j++){
			
			System.out.println("ThreedOne+++++:"+new CountTest().add());
		}
		
	}

}
package com.test.synchronize.two;

public class Test {
	public static void main(String[] args) {
		
		 ThreedOne t1= new ThreedOne();
		 ThreedOne t12= new ThreedOne();
	     new Thread(t1).start();
	     new Thread(t12).start();
	}
}
/**
 * 方法上面加了锁定,结果任然计算不对,原因在于new CountTest().add()
 * 加在实例方法(类的某个方法上),作用于当前【实例】加锁,进入同步代码前要获得【当前实例】的锁
 * 而这里的两个相同的线程每次都是new的实例,不是同一个实例。
ThreedOne+++++:1
ThreedOne+++++:2
ThreedOne+++++:3
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:4
ThreedOne+++++:6
ThreedOne+++++:6
ThreedOne+++++:8
ThreedOne+++++:7
ThreedOne+++++:9
ThreedOne+++++:10
ThreedOne+++++:11
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:12
ThreedOne+++++:13
ThreedOne+++++:14
ThreedOne+++++:15
ThreedOne+++++:16
**/

其他代码请下载代码包:
          
2. 加在代码块(某个方法的一块代码上),【指定加锁对象】,对给定对象加锁,进入同步代码库前要获得给定对象的锁
        如果是:
        synchronized (this)与锁定方法是一样的,这个this实际上也是当前类的一个实例,
        所以不同的实例对象也是锁不住的
        效果如:com.test.synchronize.four
        

package com.test.synchronize.four;


public class CountTest{
	static int i=0;
	/**
	 * 代码块的锁定synchronized (this)与锁定方法是一样的。计算结果还要靠使用这个方法的对象是不是同一个
	 * @return
	 */
	public  int add(){
		try {
			Thread.sleep(100L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized (this) {
			 i++;
		}
       
        
        return i;
    }

}
package com.test.synchronize.four;

public class ThreedOne implements Runnable{
	private CountTest countTest;
	
	public CountTest getCountTest() {
		return countTest;
	}
	public void setCountTest(CountTest countTest) {
		this.countTest = countTest;
	}
	public ThreedOne(CountTest countTest){
		this.countTest = countTest;
	}
	@Override
	public void run() {
		for(int j=0;j<10;j++){
			
			System.out.println("ThreedOne+++++:"+this.countTest.add());
		}
		
	}

}
package com.test.synchronize.four;

public class Test {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		CountTest temp2 = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp2);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 * 方法上面加了锁定,结果任然计算不对,原因在于temp和temp2 不是同一个实例
 * 加在代码块上,this相当于当前【实例】加锁,进入同步代码前要获得【当前实例】的锁
 * 而这里的两个相同的线程传递的temp和temp2 ,不是同一个实例。
ThreedOne+++++:1
ThreedOne+++++:2
ThreedOne+++++:3
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:4
ThreedOne+++++:6
ThreedOne+++++:6
ThreedOne+++++:8
ThreedOne+++++:7
ThreedOne+++++:9
ThreedOne+++++:10
ThreedOne+++++:11
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:12
ThreedOne+++++:13
ThreedOne+++++:14
ThreedOne+++++:15
ThreedOne+++++:16
**/
package com.test.synchronize.four;

public class TestSynchronized {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 * 锁定成功了,原因在于两个线程使用的temp同一个实例
 * 加在代码块上,this相当于当前【实例】加锁,进入同步代码前要获得【当前实例】的锁
ThreedOne+++++:1
ThreedOne+++++:2
ThreedOne+++++:3
ThreedOne+++++:4
ThreedOne+++++:5
ThreedOne+++++:6
ThreedOne+++++:7
ThreedOne+++++:8
ThreedOne+++++:9
ThreedOne+++++:10
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:13
ThreedOne+++++:14
ThreedOne+++++:15
ThreedOne+++++:16
ThreedOne+++++:17
ThreedOne+++++:18
ThreedOne+++++:19
ThreedOne+++++:20
**/


       如果是:
       synchronized (CountTest.class)    【指定类】加锁,即使是多个不同的实例也没有关系,也可以锁定住。
       效果如:com.test.synchronize.five

package com.test.synchronize.five;


public class CountTest{
	static int i=0;
	/**
	 * 代码块的锁定synchronized (CountTest.class)与锁定方法以及synchronized (this)是不一样的。
	 * 多个不同的实例只要是相同的对象都可以锁定
	 * @return
	 */
	public  int add(){
		try {
			Thread.sleep(100L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized (CountTest.class) {
			 i++;
		}
       
        
        return i;
    }

}
package com.test.synchronize.five;

public class ThreedOne implements Runnable{
	private CountTest countTest;
	
	public CountTest getCountTest() {
		return countTest;
	}
	public void setCountTest(CountTest countTest) {
		this.countTest = countTest;
	}
	public ThreedOne(CountTest countTest){
		this.countTest = countTest;
	}
	@Override
	public void run() {
		for(int j=0;j<50;j++){
			
			System.out.println("ThreedOne+++++:"+this.countTest.add());
		}
		
	}

}
package com.test.synchronize.five;

public class Test {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		CountTest temp2 = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp2);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 *锁定成功。 synchronized (CountTest.class)
 *
 * 加在代码块上synchronized (CountTest.class),相当于当前对类加锁,进入同步代码前要获得【当前类】的锁
 * 而这里的两个相同的线程传递的temp和temp2 ,不是同一个实例,但是是同一个类。
ThreedOne+++++:2
ThreedOne+++++:1
ThreedOne+++++:4
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:6
ThreedOne+++++:7
ThreedOne+++++:8
ThreedOne+++++:9
ThreedOne+++++:10
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:14
ThreedOne+++++:13
ThreedOne+++++:15
ThreedOne+++++:16
ThreedOne+++++:17
ThreedOne+++++:18
ThreedOne+++++:20
ThreedOne+++++:19
ThreedOne+++++:22
ThreedOne+++++:21
ThreedOne+++++:24
ThreedOne+++++:23
ThreedOne+++++:25
ThreedOne+++++:26
ThreedOne+++++:27
ThreedOne+++++:28
ThreedOne+++++:29
ThreedOne+++++:30
ThreedOne+++++:32
ThreedOne+++++:31
ThreedOne+++++:33
ThreedOne+++++:34
ThreedOne+++++:36
ThreedOne+++++:35
ThreedOne+++++:38
ThreedOne+++++:37
ThreedOne+++++:39
ThreedOne+++++:40
ThreedOne+++++:42
ThreedOne+++++:41
ThreedOne+++++:44
ThreedOne+++++:43
ThreedOne+++++:46
ThreedOne+++++:45
ThreedOne+++++:48
ThreedOne+++++:47
ThreedOne+++++:49
ThreedOne+++++:50
ThreedOne+++++:51
ThreedOne+++++:52
ThreedOne+++++:53
ThreedOne+++++:54
ThreedOne+++++:55
ThreedOne+++++:56
ThreedOne+++++:58
ThreedOne+++++:57
ThreedOne+++++:59
ThreedOne+++++:60
ThreedOne+++++:61
ThreedOne+++++:62
ThreedOne+++++:63
ThreedOne+++++:64
ThreedOne+++++:65
ThreedOne+++++:66
ThreedOne+++++:67
ThreedOne+++++:68
ThreedOne+++++:69
ThreedOne+++++:70
ThreedOne+++++:71
ThreedOne+++++:72
ThreedOne+++++:73
ThreedOne+++++:74
ThreedOne+++++:75
ThreedOne+++++:76
ThreedOne+++++:77
ThreedOne+++++:78
ThreedOne+++++:79
ThreedOne+++++:80
ThreedOne+++++:81
ThreedOne+++++:82
ThreedOne+++++:83
ThreedOne+++++:84
ThreedOne+++++:85
ThreedOne+++++:86
ThreedOne+++++:87
ThreedOne+++++:88
ThreedOne+++++:89
ThreedOne+++++:90
ThreedOne+++++:91
ThreedOne+++++:92
ThreedOne+++++:93
ThreedOne+++++:94
ThreedOne+++++:95
ThreedOne+++++:96
ThreedOne+++++:97
ThreedOne+++++:98
ThreedOne+++++:99
ThreedOne+++++:100
**/
package com.test.synchronize.five;

public class TestSynchronized {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 *锁定成功。 synchronized (CountTest.class)
 *
 * 加在代码块上synchronized (CountTest.class),相当于当前对类加锁,进入同步代码前要获得【当前类】的锁
 * 而这里的两个相同的线程传递的同一个temp ,是同一个实例,也是同一个类。
ThreedOne+++++:1
ThreedOne+++++:2
ThreedOne+++++:4
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:6
ThreedOne+++++:7
ThreedOne+++++:8
ThreedOne+++++:10
ThreedOne+++++:9
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:13
ThreedOne+++++:14
ThreedOne+++++:15
ThreedOne+++++:16
ThreedOne+++++:17
ThreedOne+++++:18
ThreedOne+++++:19
ThreedOne+++++:20
ThreedOne+++++:21
ThreedOne+++++:22
ThreedOne+++++:23
ThreedOne+++++:24
ThreedOne+++++:26
ThreedOne+++++:25
ThreedOne+++++:27
ThreedOne+++++:28
ThreedOne+++++:30
ThreedOne+++++:29
ThreedOne+++++:31
ThreedOne+++++:32
ThreedOne+++++:33
ThreedOne+++++:34
ThreedOne+++++:36
ThreedOne+++++:35
ThreedOne+++++:38
ThreedOne+++++:37
ThreedOne+++++:40
ThreedOne+++++:39
ThreedOne+++++:41
ThreedOne+++++:42
ThreedOne+++++:43
ThreedOne+++++:44
ThreedOne+++++:45
ThreedOne+++++:46
ThreedOne+++++:47
ThreedOne+++++:48
ThreedOne+++++:49
ThreedOne+++++:50
ThreedOne+++++:51
ThreedOne+++++:52
ThreedOne+++++:53
ThreedOne+++++:54
ThreedOne+++++:55
ThreedOne+++++:56
ThreedOne+++++:57
ThreedOne+++++:58
ThreedOne+++++:59
ThreedOne+++++:60
ThreedOne+++++:61
ThreedOne+++++:62
ThreedOne+++++:63
ThreedOne+++++:64
ThreedOne+++++:65
ThreedOne+++++:66
ThreedOne+++++:67
ThreedOne+++++:68
ThreedOne+++++:69
ThreedOne+++++:70
ThreedOne+++++:71
ThreedOne+++++:72
ThreedOne+++++:73
ThreedOne+++++:74
ThreedOne+++++:75
ThreedOne+++++:76
ThreedOne+++++:77
ThreedOne+++++:78
ThreedOne+++++:79
ThreedOne+++++:80
ThreedOne+++++:81
ThreedOne+++++:82
ThreedOne+++++:83
ThreedOne+++++:84
ThreedOne+++++:85
ThreedOne+++++:86
ThreedOne+++++:87
ThreedOne+++++:88
ThreedOne+++++:89
ThreedOne+++++:90
ThreedOne+++++:91
ThreedOne+++++:92
ThreedOne+++++:93
ThreedOne+++++:94
ThreedOne+++++:95
ThreedOne+++++:96
ThreedOne+++++:97
ThreedOne+++++:98
ThreedOne+++++:99
ThreedOne+++++:100
**/

3. 加在静态方法(某个类的静态方法上),作用于当前【类对象】加锁,进入同步代码前要获得【当前类对象】的锁
    public synchronized  static int add()
         可以锁定住,与synchronized (CountTest.class)效果类似。
         效果如:com.test.synchronize.six

package com.test.synchronize.six;


public class CountTest{
	static int i=0;
	/**
	 *  加在静态方法(某个类的静态方法上),作用于当前【类对象】加锁,进入同步代码前要获得【当前类对象】的锁
	 * @return
	 */
	public synchronized  static int add(){
		try {
			Thread.sleep(100L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		i++;
        return i;
    }

}
package com.test.synchronize.six;

public class ThreedOne implements Runnable{
	private CountTest countTest;
	
	public CountTest getCountTest() {
		return countTest;
	}
	public void setCountTest(CountTest countTest) {
		this.countTest = countTest;
	}
	public ThreedOne(CountTest countTest){
		this.countTest = countTest;
	}
	@Override
	public void run() {
		for(int j=0;j<50;j++){
			
			System.out.println("ThreedOne+++++:"+this.countTest.add());
		}
		
	}

}
package com.test.synchronize.six;

public class Test {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		CountTest temp2 = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp2);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 *锁定成功。public synchronized  static
 *
 * 相当于当前对类加锁,进入同步代码前要获得【当前类】的锁
 * 而这里的两个相同的线程传递的temp和temp2 ,不是同一个实例,但是是同一个类。
ThreedOne+++++:2
ThreedOne+++++:1
ThreedOne+++++:4
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:6
ThreedOne+++++:7
ThreedOne+++++:8
ThreedOne+++++:9
ThreedOne+++++:10
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:14
ThreedOne+++++:13
ThreedOne+++++:15
ThreedOne+++++:16
ThreedOne+++++:17
ThreedOne+++++:18
ThreedOne+++++:20
ThreedOne+++++:19
ThreedOne+++++:22
ThreedOne+++++:21
ThreedOne+++++:24
ThreedOne+++++:23
ThreedOne+++++:25
ThreedOne+++++:26
ThreedOne+++++:27
ThreedOne+++++:28
ThreedOne+++++:29
ThreedOne+++++:30
ThreedOne+++++:32
ThreedOne+++++:31
ThreedOne+++++:33
ThreedOne+++++:34
ThreedOne+++++:36
ThreedOne+++++:35
ThreedOne+++++:38
ThreedOne+++++:37
ThreedOne+++++:39
ThreedOne+++++:40
ThreedOne+++++:42
ThreedOne+++++:41
ThreedOne+++++:44
ThreedOne+++++:43
ThreedOne+++++:46
ThreedOne+++++:45
ThreedOne+++++:48
ThreedOne+++++:47
ThreedOne+++++:49
ThreedOne+++++:50
ThreedOne+++++:51
ThreedOne+++++:52
ThreedOne+++++:53
ThreedOne+++++:54
ThreedOne+++++:55
ThreedOne+++++:56
ThreedOne+++++:58
ThreedOne+++++:57
ThreedOne+++++:59
ThreedOne+++++:60
ThreedOne+++++:61
ThreedOne+++++:62
ThreedOne+++++:63
ThreedOne+++++:64
ThreedOne+++++:65
ThreedOne+++++:66
ThreedOne+++++:67
ThreedOne+++++:68
ThreedOne+++++:69
ThreedOne+++++:70
ThreedOne+++++:71
ThreedOne+++++:72
ThreedOne+++++:73
ThreedOne+++++:74
ThreedOne+++++:75
ThreedOne+++++:76
ThreedOne+++++:77
ThreedOne+++++:78
ThreedOne+++++:79
ThreedOne+++++:80
ThreedOne+++++:81
ThreedOne+++++:82
ThreedOne+++++:83
ThreedOne+++++:84
ThreedOne+++++:85
ThreedOne+++++:86
ThreedOne+++++:87
ThreedOne+++++:88
ThreedOne+++++:89
ThreedOne+++++:90
ThreedOne+++++:91
ThreedOne+++++:92
ThreedOne+++++:93
ThreedOne+++++:94
ThreedOne+++++:95
ThreedOne+++++:96
ThreedOne+++++:97
ThreedOne+++++:98
ThreedOne+++++:99
ThreedOne+++++:100
**/
package com.test.synchronize.six;

public class TestSynchronized {
	public static void main(String[] args) {
		CountTest temp = new CountTest();
		ThreedOne t1= new ThreedOne(temp);
		ThreedOne t12= new ThreedOne(temp);
	    new Thread(t1).start();
	    new Thread(t12).start();
	}
}
/**
 *锁定成功。public synchronized  static
 *
 * 相当于当前对类加锁,进入同步代码前要获得【当前类】的锁
 * 而这里的两个相同的线程传递的同一个temp ,是同一个实例,也是同一个类。
ThreedOne+++++:1
ThreedOne+++++:2
ThreedOne+++++:4
ThreedOne+++++:3
ThreedOne+++++:5
ThreedOne+++++:6
ThreedOne+++++:7
ThreedOne+++++:8
ThreedOne+++++:10
ThreedOne+++++:9
ThreedOne+++++:11
ThreedOne+++++:12
ThreedOne+++++:13
ThreedOne+++++:14
ThreedOne+++++:15
ThreedOne+++++:16
ThreedOne+++++:17
ThreedOne+++++:18
ThreedOne+++++:19
ThreedOne+++++:20
ThreedOne+++++:21
ThreedOne+++++:22
ThreedOne+++++:23
ThreedOne+++++:24
ThreedOne+++++:26
ThreedOne+++++:25
ThreedOne+++++:27
ThreedOne+++++:28
ThreedOne+++++:30
ThreedOne+++++:29
ThreedOne+++++:31
ThreedOne+++++:32
ThreedOne+++++:33
ThreedOne+++++:34
ThreedOne+++++:36
ThreedOne+++++:35
ThreedOne+++++:38
ThreedOne+++++:37
ThreedOne+++++:40
ThreedOne+++++:39
ThreedOne+++++:41
ThreedOne+++++:42
ThreedOne+++++:43
ThreedOne+++++:44
ThreedOne+++++:45
ThreedOne+++++:46
ThreedOne+++++:47
ThreedOne+++++:48
ThreedOne+++++:49
ThreedOne+++++:50
ThreedOne+++++:51
ThreedOne+++++:52
ThreedOne+++++:53
ThreedOne+++++:54
ThreedOne+++++:55
ThreedOne+++++:56
ThreedOne+++++:57
ThreedOne+++++:58
ThreedOne+++++:59
ThreedOne+++++:60
ThreedOne+++++:61
ThreedOne+++++:62
ThreedOne+++++:63
ThreedOne+++++:64
ThreedOne+++++:65
ThreedOne+++++:66
ThreedOne+++++:67
ThreedOne+++++:68
ThreedOne+++++:69
ThreedOne+++++:70
ThreedOne+++++:71
ThreedOne+++++:72
ThreedOne+++++:73
ThreedOne+++++:74
ThreedOne+++++:75
ThreedOne+++++:76
ThreedOne+++++:77
ThreedOne+++++:78
ThreedOne+++++:79
ThreedOne+++++:80
ThreedOne+++++:81
ThreedOne+++++:82
ThreedOne+++++:83
ThreedOne+++++:84
ThreedOne+++++:85
ThreedOne+++++:86
ThreedOne+++++:87
ThreedOne+++++:88
ThreedOne+++++:89
ThreedOne+++++:90
ThreedOne+++++:91
ThreedOne+++++:92
ThreedOne+++++:93
ThreedOne+++++:94
ThreedOne+++++:95
ThreedOne+++++:96
ThreedOne+++++:97
ThreedOne+++++:98
ThreedOne+++++:99
ThreedOne+++++:100
**/

全部的代码可以到这里进行下载:https://download.youkuaiyun.com/download/tianshi1017/10741784

<think>嗯,用户问的是Javasynchronized用法案例。首先,我需要回忆一下synchronized的基本概念。synchronizedJava中是用来控制多线程对共享资源的访问,避免线程冲突数据不一致的问题。主要的作用是确保同一时间只有一个线程可以执行某个方法或代码块。 接下来,我得考虑synchronized几种使用方式。常见的应该有三种:实例方法同步、静态方法同步同步代码块。实例方法同步是给当前对象实例加,而静态方法同步则是给的Class对象加,因为静态方法属于级别。同步代码块的话,可以更灵活地指定对象,这样可以在不同的代码块使用不同的,提高并发效率。 然后,每个使用方式都需要具体的例子来说明。比如实例方法同步,可以举一个计数器的例子,多个线程调用increment方法,如果不加synchronized的话,可能会出现计数错误。加上synchronized后,就能保证原子性操作。 静态方法同步的例子可能需要一个静态计数器,同样用多个线程来测试。同步代码块的话,可以演示使用不同的对象,或者使用this对象,这样用户能理解不同的作用范围。 另外,需要提到的释放机制。synchronized是自动获取释放的,进入同步块或方法时获取,退出时释放,无论是正常退出还是异常退出,这样能避免死的情况,不过实际开发中还是要注意的嵌套问题。 可能用户还会关心synchronized的底层实现,比如monitor机制,对象头中的monitor指针,以及JVM如何管理的获取释放。不过这部分可能属于进阶内容,用户如果没有问的话,可能不需要深入,但可以稍微提一下,让回答更全面。 案例部分要具体,最好是能运行的代码示例,这样用户能直接看到效果。比如计数器,创建多个线程,每个线程循环增加计数,最后输出结果,对比加不加的情况下的结果差异。这样用户能直观地理解synchronized的作用。 还要注意可能存在的误区,比如对象的选择。如果同步代码块使用不同的对象,可能无法正确同步,导致线程安全问题。比如如果两个线程分别使用不同的对象,那么它们的同步块不会互斥,这时候需要确保所有线程使用的是同一个对象。 另外,synchronized的可重入性也是一个点,同一个线程可以多次获取同一个,不会自己阻塞自己,这在递归调用或者多个同步方法互相调用时很重要。 最后,总结一下synchronized的优缺点。优点是使用简单,自动管理,不容易出错;缺点是性能相比Lock接口可能稍差,尤其是在高竞争环境下,但现代JVM对synchronized做了很多优化,比如偏向、轻量级、自旋等,所以性能差距已经缩小了很多。 在写案例的时候,要确保代码正确,语法无误,特别是同步块的作用范围是否正确,对象是否恰当。例如,在同步代码块的例子中,使用thisCounter.class作为对象的不同场景。 可能还需要提醒用户,虽然synchronized能解决线程安全问题,但过度使用会导致性能下降,因为同一时间只有一个线程能执行同步代码,所以要根据实际情况合理设计同步范围,尽量减少同步的代码量,提高并发性能。 总之,回答的结构需要先介绍synchronized的作用,然后分点讲解不同的使用方式,每种方式给出示例代码,并解释代码的执行结果原理,最后总结注意事项最佳实践。</think>以下为分步讲解`synchronized`的用法案例: --- ### 一、synchronized 核心作用 保证**多线程环境下**对共享资源的**原子性****可见性**,避免数据竞争状态不一致。 --- ### 二、三种使用方式及案例 #### 1. 同步实例方法 - **对象**:当前实例(`this`) - **适用场景**:保护非静态变量的线程安全 ```java class Counter { private int count = 0; // 同步实例方法 public synchronized void increment() { count++; // 原子操作 } public int getCount() { return count; } } // 测试代码 public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(counter.getCount()); // 输出 2000 } ``` --- #### 2. 同步静态方法 - **对象**:的`Class`对象(`Counter.class`) - **适用场景**:保护静态变量的线程安全 ```java class StaticCounter { private static int count = 0; // 同步静态方法 public static synchronized void increment() { count++; } public static int getCount() { return count; } } // 测试代码(似实例方法测试,所有线程共享静态方法) ``` --- #### 3. 同步代码块 - **对象**:可指定任意对象(推荐使用专用对象) - **优势**:缩小同步范围,提高性能 ```java class BlockCounter { private int count = 0; private final Object lock = new Object(); // 专用对象 public void increment() { synchronized (lock) { // 显式指定对象 count++; } } } // 其他用法 public void method() { // 同步当前实例 synchronized (this) { // ... } // 同步对象 synchronized (BlockCounter.class) { // ... } } ``` --- ### 三、底层原理 通过**对象监视器(Monitor)**实现: 1. 每个Java对象关联一个Monitor 2. 线程执行`synchronized`代码前需获取Monitor 3. 获取成功则标记为定状态,其他线程进入阻塞队列 --- ### 四、关键注意事项 1. **对象一致性**:所有线程必须使用**同一个对象**才能生效 2. **避免粒度问题**:同步范围过大降低性能,过小导致线程不安全 3. **可重入性**:同一线程可重复获取已持有的 4. **非公平**:默认抢占顺序不保证公平性 --- ### 五、典型应用场景 1. 单例模式(双重检查) ```java public class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` 2. 线程安全的集合操作 ```java List<String> syncList = Collections.synchronizedList(new ArrayList<>()); ``` --- ### 六、与Lock的区别 | 特性 | synchronized | Lock接口 | |--------------------|--------------------|--------------------| | 获取方式 | 自动获取/释放 | 需手动lock/unlock | | 可中断 | 否 | 是 | | 公平性 | 非公平 | 可配置 | | 条件变量 | 单一等待队列 | 支持多个Condition | --- 通过合理使用`synchronized`,可以有效解决多线程环境下的线程安全问题。实际开发中应根据具体场景选择同步策略,并注意控制粒度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值