Synchronized相关

简介:

synchronized的说明

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

synchronized与static synchronized区别

说明

synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”,类的两个不同实例就没有这种约束了。

那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码块。

实际上,如果在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,该类也就有一个监视块,监视线程并发访问改实例synchronized保护块。而static synchronized则是该类的所有实例公用一个监视块,这便是两个的区别了。

也就是synchronized相当于 this.synchronized,而static synchronized相当于Something.synchronized.

结论:

A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。

例程

例如下面函数,创建了20个线程,每个线程都对race进行100000次累加,加static和不加static的increase函数,将会得到不同的结果。

例程一

对于不加static 参数的increase() 函数,如果在同一个实例中调用,将能得到预期的结果(最终输出的race都会等于200000):

</pre>
<pre>package chapter12;
class TestStatic {
 public static volatile int race = 0;
 public synchronized void increase() {
 race ++ ;
 }
}
public class StaticTest {
 public static void main(String[] args) {
 final TestStatic test = new TestStatic();
 Thread[] threads = new Thread[20];
 for(int i=0 ; i<20 ;i++) {
 threads[i] = new Thread(new Runnable(){
 @Override
 public void run() {
 for(int j = 0 ; j<100000 ; j++) {
 test.increase();
 }
 }
 });
 threads[i].start();
 }
 while(Thread.activeCount()>1) {
 Thread.yield();
 }
 System.out.println(TestStatic.race);
 }
}</pre>
<pre>

例程二

对于不加static 参数的increase() 函数,如果在多个实例中调用,将不能得到预期的结果(最终输出的race都会小于200000):

package chapter12;
class TestStatic {
    public static volatile int race = 0;
    public synchronized void increase() {
        race ++ ;
    }
}
public class StaticTest {
    public static void main(String[] args) {
        Thread[] threads = new Thread[20];
        for(int i=0 ; i<20 ;i++) {
            threads[i] = new Thread(new Runnable(){
                TestStatic test = new TestStatic();
                @Override
                public void run() {
                    for(int j = 0 ; j<100000 ; j++) {
                        test.increase();
                    }
                }
            });
            threads[i].start();
        }
        while(Thread.activeCount()>1) {
            Thread.yield();
        }
        System.out.println(TestStatic.race);
    }
}

例程三

对于加上了static 参数的increase() 函数,不管是在多个实例中、还是在同一个实例中被调用,将都能得到预期的结果(最终输出的race都会
package chapter12;
class TestStatic {
    public static volatile int race = 0;
    public static synchronized void increase() {
        race ++ ;
    }
}
public class StaticTest {
    public static void main(String[] args) {
//      final TestStatic test = new TestStatic();
        Thread[] threads = new Thread[20];
        for(int i=0 ; i<20 ;i++) {
            threads[i] = new Thread(new Runnable(){
                TestStatic test = new TestStatic();
                @Override
                public void run() {
                    for(int j = 0 ; j<100000 ; j++) {
                        test.increase();
                    }
                }
            });
            threads[i].start();
        }
        while(Thread.activeCount()>1) {
            Thread.yield();
        }
        System.out.println(TestStatic.race);
    }
}

题目

(一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:

pulbic class Something(){

public synchronized void isSyncA(){}

public synchronized void isSyncB(){}

public static synchronized void cSyncA(){}

public static synchronized void cSyncB(){}

}

那么,加入有Something类的两个实例a与b,那么下列组方法可以被1个以上线程同时访问呢

a.   x.isSyncA()与x.isSyncB()

b.   x.isSyncA()与y.isSyncA()

c.   x.cSyncA()与y.cSyncB()

d.   x.isSyncA()与Something.cSyncA()

这里,很清楚的可以判断:

a,都是对同一个实例的synchronized域访问,因此不能被同时访问

b,是针对不同实例的,因此可以同时被访问

c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与   Something.isSyncB()了,因此不能被同时访问。

d,书上的答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。

个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。目前还不是分清楚java内部设计synchronzied是怎么样实现的。)

synchronized方法与synchronized代码块的区别

synchronized methods(){} 与synchronized(this){}之间没有什么区别,只是 synchronized methods(){} 便于阅读理解。

而synchronized(this){}可以更精确的控制冲突限制访问区域,有时候表现更高效率, 它的作用域是当前对象。

synchronized关键字是不能继承的

继承时子类的覆盖方法必须显示定义成synchronized。

也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法

 

相关文章
|
8月前
总结 synchronized
总结 synchronized
31 0
|
4月前
|
存储 安全 Java
|
4月前
synchronized与ReentrantLock区别与联系
synchronized与ReentrantLock区别与联系
22 0
|
6月前
|
安全 算法 Java
synchronized 同步锁
Java中的synchronized关键字用于实现线程同步,可以修饰方法或代码块。 1. 修饰方法:当一个方法被synchronized修饰时,只有获得该方法的锁的线程才能执行该方法。其他线程需要等待锁的释放才能执行该方法。 2. 修饰代码块:当某个对象被synchronized修饰时,任何线程在执行该对象中被synchronized修饰的代码块时,必须先获得该对象的锁。其他线程需要等待锁的释放才能执行同步代码块。Java中的每个对象都有一个内置锁,当一个对象被synchronized修饰时,它的内置锁就起作用了。只有获得该锁的线程才能访问被synchronized修饰的代码段。使用synch
38 0
|
6月前
ReentrantLock和Synchronized简单比较
ReentrantLock和Synchronized简单比较
19 0
|
7月前
Synchronized
作用:能够保证在同一时刻最多有一个线程执行该段代码,以保证并发的安全性。(当第一个线程去执行该段代码的时候就拿到锁,并独占这把锁,当方法执行结束或者一定条件后它才释放这把锁,在没释放锁之前,所有的线程处于等待状态)
32 0
|
9月前
|
Java
synchronized的总结
synchronized的总结
synchronized的总结
|
9月前
|
程序员
ReentrantLock与synchronized的区别
ReentrantLock与synchronized的区别
|
9月前
|
前端开发 Java Spring
方法上加上 synchronized 就可以了么
方法上加上 synchronized 就可以了么
|
9月前
|
存储 缓存 安全
synchronized的简单理解
synchronized的简单理解
66 0