synchronized是java的关键字,他有以下特性。
互斥性:同一个时间只允许一个线程获取到某个对象锁,这样就可以保证线程安全,同一时间只有一个线程可以对代码进行访问操作。互斥性也就是我们经常说的原子性。
可见性:必须保证在锁被释放前,对数据的修改 对其他线程是可见的,否则其他线程从其他地方获取数据导致不一致性。
synchronized是隐式锁,是jvm内置锁,不需要手动加锁与解锁,jvm会自动加锁跟解锁。
而lock则需要实现lock接口,需要手动加锁和解锁。
下面代码实例从三个方面进行加锁。
- 静态方法,锁的是类对象。
- 普通方法,锁的是实例对象。
(需要注意:在spring容器中,bean是单实例,否则加synchronized没什么意义)
- 代码块:锁的是括号里的对象。
/** * @author keying */ public class Synchronized822 { public static void main(String[] args) throws InterruptedException { ThreadTestNei threadTestNei = new ThreadTestNei(); ThreadA threadA = new ThreadA(threadTestNei); threadA.setName("A-THREAD"); threadA.start(); ThreadB threadB = new ThreadB(threadTestNei); threadB.setName("B-THREAD"); threadB.start(); } } class ThreadA extends Thread { private ThreadTestNei threadTestNei; ThreadA(ThreadTestNei threadTestNei) { this.threadTestNei = threadTestNei; } @Override public void run() { super.run(); threadTestNei.setUser(); } } class ThreadB extends Thread { private ThreadTestNei threadTestNei; ThreadB(ThreadTestNei threadTestNei) { this.threadTestNei = threadTestNei; } @Override public void run() { super.run(); threadTestNei.setUser(); } } @Data class ThreadTestNei { private String name; private String aString = new String(); public void setUser() { try { synchronized (aString) { System.out.println(Thread.currentThread().getName() + "----" + "begin"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "----" + "end"); } } catch (Exception e) { } } }
这时候他们修饰的是同一个对象,所以 输出是
A-THREAD----begin A-THREAD----end B-THREAD----begin B-THREAD----end
当代码改为
try { String aString = new String(); synchronized (aString) { System.out.println(Thread.currentThread().getName() + "----" + "begin"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "----" + "end"); } } catch (Exception e) { }
输出则是:
A-THREAD----begin B-THREAD----begin A-THREAD----end B-THREAD----end
如果锁住的是类,则输出的是
try { synchronized (ThreadTestNei.class) { System.out.println(Thread.currentThread().getName() + "----" + "begin"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "----" + "end"); } } catch (Exception e) { } A-THREAD----begin A-THREAD----end B-THREAD----begin B-THREAD----end