synchronized的用法以及常见的使用错误
来源:互联网 发布:java实现群发短信 编辑:程序博客网 时间:2024/06/06 13:59
synchronized的作用是实现线程之间的同步,既能保证可见性,又能保证原子性。
用法也有很多种,如下所示
用一个线程类来演示下这三种:
指定加锁对象:
package com.bckj.Thread;/** * Created by Admin on 2017/6/23. */public class SynchronizedTest { static int x; static class AddThread implements Runnable{ Object o = new Object(); @Override public synchronized void run() { for(int i=1;i<=1000;i++){ synchronized (o){ x++; } } } } public static void main(String[] args) throws InterruptedException { Runnable run = new AddThread(); Thread addThread1 = new Thread(run); Thread addThread2 = new Thread(run); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}
直接作用于实例方法:
package com.bckj.Thread;/** * Created by Admin on 2017/6/23. */public class SynchronizedTest { static int x; static class AddThread implements Runnable{ public synchronized void increase(){ x++; } @Override public synchronized void run() { for(int i=1;i<=1000;i++){ increase(); } } } public static void main(String[] args) throws InterruptedException { Runnable run = new AddThread(); Thread addThread1 = new Thread(run); Thread addThread2 = new Thread(run); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}
直接作用于静态方法:
package com.bckj.Thread;/** * Created by Admin on 2017/6/23. */public class SynchronizedTest { static int x; static class AddThread implements Runnable{ public synchronized static void increase(){ x++; } @Override public synchronized void run() { for(int i=1;i<=1000;i++){ increase(); } } } public static void main(String[] args) throws InterruptedException { Runnable run = new AddThread(); Runnable run2 = new AddThread(); Thread addThread1 = new Thread(run); Thread addThread2 = new Thread(run2); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}
因为要体现静态方法,所以实例化了两个不同的AddThread对象。
新手使用synchronized的时候可能会犯下面的错误(不久前我也刚犯过)
1、
public class SynchronizedTest { static int x; static class AddThread implements Runnable{ public synchronized void increase(){ x++; } @Override public void run() { for(int i=1;i<=1000;i++){ increase(); } } } public static void main(String[] args) throws InterruptedException { Runnable run = new AddThread(); Runnable run2 = new AddThread(); Thread addThread1 = new Thread(run); Thread addThread2 = new Thread(run2); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}
public class SynchronizedTest { static int x; static class AddThread implements Runnable{ Object o = new Object(); @Override public void run() { for(int i=1;i<=1000;i++){ synchronized (o){ x++; } } } } public static void main(String[] args) throws InterruptedException { Thread addThread1 = new Thread(new AddThread()); Thread addThread2 = new Thread(new AddThread()); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}
这两种都是对线程对象中的方法或局部变量进行加锁,但是又实例化了两个不同的Runnable实例,也就是说这两个线程使用的是两把不同的锁,因此不能保证线程安全,最后x的结果也会<=2000。
2、
第二种错误就比较隐晦
public class AddThread implements Runnable{ static Integer x = 0; @Override public void run() { for(int i=1;i<=1000;i++){ synchronized (x){ x++; } } } public static void main(String[] args) throws InterruptedException { Runnable run = new AddThread(); Thread addThread1 = new Thread(run); Thread addThread2 = new Thread(run); addThread1.start(); addThread2.start(); //让主线程等待上面两个线程执行完毕 addThread1.join(); addThread2.join(); System.out.println(x); }}这个程序看似没有错误,但是执行结果会得到比2000小的数值,主要是由于,Integer是不可变对象,对象一旦创建就不可能被修改。
通过javap反编译run方法可以看到:
可以看到i++在执行的时候变成了 i=Integer.valueOf(i.intValue()+1);
Integer.valueOf():
他会倾向于返回一个代表指定数值的Integer实例。因此,i++的本质是,创建一个新的Integer对象,并将它的引用赋值给i。
这样的话,就可以知道了,因为i这个对象可能一直在变,所以锁的对象一直在变,因此不能起到线程同步的作用,只要改成上面提到第一种用法的例子那样就可以解决。
阅读全文
0 0
- synchronized的用法以及常见的使用错误
- AspNetPager分页控件的使用以及常见错误
- java线程以及synchronized关键字的使用
- Synchronized的使用以及实现原理
- synchronized的用法
- synchronized的用法
- synchronized的用法
- synchronized的用法
- synchronized的用法
- synchronized的用法
- synchronized的用法简介
- synchronized的用法
- synchronized的用法汇总
- synchronized关键字的用法
- java的synchronized用法
- synchronized的用法
- @synchronized(self)的用法
- Synchronized的用法
- 美团CodeM编程大赛资格赛题解
- 设计模式之一:责任链
- java中 string和int boolean类型值true和String String类型值"true"和boolean类型 三种相互转换
- tomcat启动报错 It is not a Java .class file
- Codeforces 4C Registration system 题解
- synchronized的用法以及常见的使用错误
- 网络编程send和recv
- Java之this关键词的使用详解
- poj1088滑雪
- 移植vsftpd到ARM开发板
- 编译原理填空题
- SAPUI5教程——can not load launchpad Tile问题解决方案
- Python 刷题日记:LeetCode 624. Maximum Distance in Arrays
- 网络字节序与字节内比特序