Java并发编程:synchronized(2)

  1)当一个线程正在访问一个对象的synchronized方法,那么其他线程不能访问该对象的其他synchronized方法。这个原因很简单,因为一个对象只有一把锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized方法。

  2)当一个线程正在访问一个对象的synchronized方法,那么其他线程能访问该对象的非synchronized方法。这个原因很简单,访问非synchronized方法不需要获得该对象的锁,假如一个方法没用synchronized关键字修饰,说明它不会使用到临界资源,那么其他线程是可以访问这个方法的,

  3)如果一个线程A需要访问对象object1的synchronized方法fun1,另外一个线程B需要访问对象object2的synchronized方法fun1,即使object1和object2是同一类型),也不会产生线程安全问题,因为他们访问的是不同的对象,所以不存在互斥问题。

  2.synchronized代码块

  synchronized代码块类似于以下这种形式:

synchronized(synObject) {

}

  当在某个线程中执行这段代码块,该线程会获取对象synObject的锁,从而使得其他线程无法同时访问该代码块。

  synObject可以是this,代表获取当前对象的锁,也可以是类中的一个属性,代表获取该属性的锁。

  比如上面的insert方法可以改成以下两种形式:

class InsertData {

private ArrayList<Integer> arrayList = new ArrayList<Integer>();

public void insert(Thread thread){

synchronized (this) {

for(int i=0;i<100;i++){

System.out.println(thread.getName()+"在插入数据"+i);

arrayList.add(i);

}

}

}

}

class InsertData {

private ArrayList<Integer> arrayList = new ArrayList<Integer>();

private Object object = new Object();

public void insert(Thread thread){

synchronized (object) {

for(int i=0;i<100;i++){

System.out.println(thread.getName()+"在插入数据"+i);

arrayList.add(i);

}

}

}

}

  从上面可以看出,synchronized代码块使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题,synchronized代码块可以实现只对需要同步的地方进行同步。

  另外,每个类也会有一个锁,它可以用来控制对static数据成员的并发访问。

  并且如果一个线程执行一个对象的非static synchronized方法,另外一个线程需要执行这个对象所属类的static synchronized方法,此时不会发生互斥现象,因为访问static synchronized方法占用的是类锁,而访问非static synchronized方法占用的是对象锁,所以不存在互斥现象。

看下面这段代码就明白了:

public class Test {

public static void main(String[] args)  {

final InsertData insertData = new InsertData();

new Thread(){

@Override

public void run() {

insertData.insert();

}

}.start(); 

new Thread(){

@Override

public void run() {

insertData.insert1();

}

}.start();

}

class InsertData { 

public synchronized void insert(){

System.out.println("执行insert");

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("执行insert完毕");

}

public synchronized static void insert1() {

System.out.println("执行insert1");

System.out.println("执行insert1完毕");

}

}

  执行结果;

Java并发编程:synchronized

  第一个线程里面执行的是insert方法,不会导致第二个线程执行insert1方法发生阻塞现象。

  下面我们看一下synchronized关键字到底做了什么事情,我们来反编译它的字节码看一下,下面这段代码反编译后的字节码为:

public class InsertData {

private Object object = new Object();

public void insert(Thread thread){

synchronized (object) {

}

}

public synchronized void insert1(Thread thread){

}

public void insert2(Thread thread){

}

}

Java并发编程:synchronized

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2ea3f1f5ac8f6c9f64a9e09a7501a6fb.html