萱草|synchronized关键字,老师发糖了,要排排队领取哦!Java( 二 )

<5;i++){System.out.println("线程"+thread.getName()+"在插入数据"+i);list.add(i);}}}输出结果可以看出:两个线程在同时执行insert方法 , 不存在相互等待的情况 。
线程Thread-0在插入数据0线程Thread-1在插入数据0线程Thread-0在插入数据1线程Thread-1在插入数据1线程Thread-0在插入数据2线程Thread-0在插入数据3线程Thread-1在插入数据2线程Thread-0在插入数据4线程Thread-1在插入数据3线程Thread-1在插入数据4下面我们在insert方法前面加上关键字synchronized:
classInsertData{privateListlist=newArrayList();publicsynchronizedvoidinsert(Threadthread){for(inti=0;i<5;i++){System.out.println("线程"+thread.getName()+"在插入数据"+i);list.add(i);}}}输出结果可以看出:Thread-1插入数据是等Thread-0插入完数据之后才进行的 。 说明Thread-0和Thread-1是顺序执行insert方法的 。
线程Thread-0在插入数据0线程Thread-0在插入数据1线程Thread-0在插入数据2线程Thread-0在插入数据3线程Thread-0在插入数据4线程Thread-1在插入数据0线程Thread-1在插入数据1线程Thread-1在插入数据2线程Thread-1在插入数据3线程Thread-1在插入数据4注意:
1)当一个线程正在访问一个对象的synchronized方法 , 那么其他线程不能访问该对象的其他synchronized方法 。 这个原因很简单 , 因为一个对象只有一把锁 , 当一个线程获取了该对象的锁之后 , 其他线程无法获取该对象的锁 , 所以无法访问该对象的其他synchronized方法 。
2)当一个线程正在访问一个对象的synchronized方法 , 那么其他线程能访问该对象的非synchronized方法 。 这个原因很简单 , 访问非synchronized方法不需要获得该对象的锁 , 假如一个方法没用synchronized关键字修饰 , 说明它不会使用到临界资源 , 那么其他线程是可以访问这个方法的 ,
3)如果一个线程A需要访问对象object1的synchronized方法fun1 , 另外一个线程B需要访问对象object2的synchronized方法fun1 , 即使object1和object2是同一类型) , 也不会产生线程安全问题 , 因为他们访问的是不同的对象 , 所以不存在互斥问题 。
②synchronized代码块
synchronized代码块类似于以下这种形式:
synchronized(synObject){}当在某个线程中执行这段代码块 , 该线程会获取对象synObject的锁 , 从而使得其他线程无法同时访问该代码块 。
synObject可以是this , 代表获取当前对象的锁 , 也可以是类中的一个属性 , 代表获取该属性的锁 。
比如上面的insert方法可以改成以下两种形式:
classInsertData{privateListlist=newArrayList();publicvoidinsert(Threadthread){synchronized(this){for(inti=0;i<5;i++){System.out.println("线程"+thread.getName()+"在插入数据"+i);list.add(i);}}}}classInsertData{privateListlist=newArrayList();privateObjectobject=newObject();publicvoidinsert(Threadthread){synchronized(object){for(inti=0;i<5;i++){System.out.println("线程"+thread.getName()+"在插入数据"+i);list.add(i);}}}}从上面可以看出 , synchronized代码块使用起来比synchronized方法要灵活得多 。 因为也许一个方法中只有一部分代码只需要同步 , 如果此时对整个方法用synchronized进行同步 , 会影响程序执行效率 。 而使用synchronized代码块就可以避免这个问题 , synchronized代码块可以实现只对需要同步的地方进行同步 。
另外 , 每个类也会有一个锁 , 它可以用来控制对static数据成员的并发访问 。
并且如果一个线程执行一个对象的非staticsynchronized方法 , 另外一个线程需要执行这个对象所属类的staticsynchronized方法 , 此时不会发生互斥现象 , 因为访问staticsynchronized方法占用的是类锁 , 而访问非staticsynchronized方法占用的是对象锁 , 所以不存在互斥现象 。