多个线程执行对同一个Java对象访问时候,为了保证数据的有效性,通常会使用synchronized关键字,俗称多线程安全。
synchronized从语法上一共有三种语法,修饰静态方法,修饰实例方法,在方法中使用代码块。
从锁住的对象来看两种:锁住类和和实例对象。
锁住实例对象:无论多少个线程使用同一个实例对象,都需要排队。但是多个线程使用多个对象,就不用排队了。
锁住类:无论多少个对象,只要对象都是一个类,多个线程使用多个对象,依旧要排队。
注意:一定要检查对象是不是实例对象,局部/静态变量是无法锁住的。
上述例子,可以用以下代码进行简单测试。
public class work01 { public static void main(String[] args) throws InterruptedException { MyThread myThread=new MyThread();//同一个对象 Thread t1=new Thread(myThread,"t1");Thread t2=new Thread(myThread,"t2"); t1.start();t2.start(); } } class MyThread extends Thread{ count c=new count();//必须是实例对象 public void run(){ c.m1(); } } class count{ public void m1(){ synchronized (this){ for (int i = 0; i <30 ;i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } } }总结:
无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是类,该类所有的对象同一把锁。实现同步是要很大的系统开销作为代价的,可能造成死锁,所以尽量避免无谓的同步控制。优先使用局部变量,局部变量在栈区,是不共享的,静态变量在方法区中,实例变量在堆中,堆和方法区都是共享的。