java同步synchronized

synchronized可以修饰非静态成员方法,修饰静态成员方法,修饰代码块,作用都是同步,但是肯定有区别的,下区分别说明:


一、synchronized修饰非静态成员方法:

在不同线程中使用同一个对象去调用该方法时,一但对象调用了方法,那么方法执行过程中,再使用同一个对象再调用该方法会被阻塞起来,直到方法执行结束!但是如果使用同一个类的不同对象去访问就起不了使用了。

        例:

//Test.java

public class Test {

public synchronized void show(String name) throws InterruptedException {

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

System.out.println(name + i);

Thread.sleep(1000);

}

}

}


//MyThread.java

public class MyThread extends Thread {

private String name;

private Test  test;

public MyThread(String name, Test test)  {

this.name = name;

this.test = test;

}

@Override

public void run() {

try {

this.test.show(this.name);

catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Test test = new Test();

Thread thread1 = new MyThread("小明",test);

Thread thread2 = new MyThread("小华",test);

thread1.start();

thread2.start();

}

}

运行结果为

小明0
小明1
小明2
小明3
小明4
小华0
小华1
小华2
小华3
小华4


上面的示例分析:

 上面main入口方法中,两个线程对象中都传了同一个Test类的对象test,所以MyThread类中的run函数不管是thread1.start()还是thread2.start()开线程都使用

同一个对象test去调用show(Strint name)函数,所以show函数同步起使用了


如果main入口方法改为:

public static void main(String[] args) {

Test test1 = new Test();

Test test2 = new Test();

Thread thread1 = new MyThread("小明",test1);

Thread thread2 = new MyThread("小华",test2);

thread1.start();

thread2.start();

}

那么

thread1.start();thread2.start();起动线程后,run函数中分别使用了test1对象与test2对象去访问了show(String name)函数,同步就不会起使用了,即改成这样后

打印结果为:

小明0
小华0
小明1
小华1
小明2
小华2
小明3
小华3
小明4
小华4


二、synchronized修饰静态成员方法:  

只要该方法被调用,都会被同步,

例:把上面例中Test中的show方法使用static修饰,任何情况下调用show函数,函数都会被同步

public class Test {

public static synchronized void show(String name) throws InterruptedException {

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

System.out.println(name + i);

Thread.sleep(1000);

}

}

}

执行结果要么是

小明0
小明1
小明2
小明3
小明4
小华0
小华1
小华2
小华3
小华4

要么是

小华0
小华1
小华2
小华3
小华4
小明0
小明1
小明2
小明3
小明4


三、同步代码块: 可以让一个方法中部分代码被同步,当同步生效时,多个线程不能同时访问代码块中,会阻塞等待。但是也只能同步相同对象去访问有同步代码块的方法,

使用同一个类的不同对象去访问,同步不会生效。

例 1:

//Test.java

public class Test {

public void show(String name) throws InterruptedException {

synchronized (this) {

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

System.out.println(name + i);

Thread.sleep(1000);

}

}

}

}

//MyThread.java

public class MyThread extends Thread {

private String name;

private Test  test;

public MyThread(String name, Test test)  {

this.name = name;

this.test = test;

}

@Override

public void run() {

try {

this.test.show(this.name);

catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Test test = new Test();

Thread thread1 = new MyThread("小明",test);

Thread thread2 = new MyThread("小华",test);

thread1.start();

thread2.start();

}

}

同步生效: 运行结果为

小明0
小明1
小明2
小明3
小明4
小华0
小华1
小华2
小华3
小华4

例2:

如果main入口方法改为:

public static void main(String[] args) {

Test test1 = new Test();

Test test2 = new Test();

Thread thread1 = new MyThread("小明",test1);

Thread thread2 = new MyThread("小华",test2);

thread1.start();

thread2.start();

}

那么同步不起使用了

打印结果为:

小明0
小华0
小明1
小华1
小明2
小华2
小明3
小华3
小明4
小华4









 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值