您的位置:首页 > 编程语言 > Java开发

JAVA synchronized关键字详解

2016-12-20 00:00 453 查看
#并发的问题
在java多线程编程中,我们碰到的最大的问题就是资源竞争,这令我们的正常程序流程变得复杂而诡异。

看下面这段代码:

class Test {
public void test() {
System.out.println("Start...");
sleep(100);
System.out.println("end");
}
}

public class main {
public static void main(String[] argv) {
for(int i=0;i<3;i++)
new Thread( ()-> new Test().test()) .start();
}
}


输出: Start... Start... Start... end end end

为什么会这样呢?不同的线程进入了相同的函数体内,同时运行

就造成了线程之间的资源竞争了

#关键字synchronize
Java语言本身提供了关键字synchronize,用于对于竞争的资源加锁
synchronize标识函数与代码块.

标识函数的时候,函数为static时候为全局锁,普通时为对象锁

public synchronized void test();
public static synchronized void test();


标识代码块的时候,括号内为使用范围

//对象锁
public void test() {
synchronized(this){
}
}
//全局锁
public void test() {
synchronized(Test.class){
}
}

什么是对象锁呢,意思是只有相同的Test对象调用test()方法时,加锁才有用

比如:

// synchronized(this) 锁只能锁住当前的this对象
// 也就是由同一个Test类生成的实例对象 调用test()时才会生效
// 但是由不同的对象调用代码时,是无效的
//
// 如果真的想使用全局的锁效果
// 1:方法加入static,静态方法是没有this的,所以默认则是整个类的对象
// 2:synchronized( Test.class )  这样锁住的就是整个类的对象了
//
class Test {
public synchronized void test() {
System.out.println("Start...");
sleep();
System.out.println("end");
}
}

public class main {
public static void main(String[] argv) {
Test t = new Test();
for(int i=0;i<3;i++)
new Thread( () -> t.test()) .start();
}
}

可以看到,每个线程都是用的同一个Test类对象
此时测试结果是正常的:

Start... end Start... end Start... end

如果想要不使用同一个对象呢 ?

这时候重新修改下开始的例子,由于我是用每次都 new Test( ) 调用的

所以这里应该添加全局锁:

class Test {
public static synchronized void test() {
System.out.println("Start...");
Test.sleep();
System.out.println("end");
}
}

输出结果:

Start... end Start... end Start... end

或者不想添加为静态方法时,可以将test()方法改为:
synchronized (Test.class)

public void test() {
synchronized (Test.class){
System.out.println("Start...");
sleep();
System.out.println("end");
}
}

这个也是正常的, 和静态方法的作用相同了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 多线程 并发