Java synchronized的实现原理与应用
来源:互联网 发布:大众软件多久一期 编辑:程序博客网 时间:2024/05/18 00:40
在多线程中synchronized应该是我们运用的最多的,很多人会称呼它为重量级锁。java中的每一个对象都可以作为锁。具体表现为以下三种形式。
对于普通同步方法,锁是当前实例对象。
//图书class Books {private int id;// 图书IDprivate String name; // 图书名称private int number; // 图书数量//存书public void stockBooks(int count) {number+=count;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}//借书public void taskBooks(int count) {number-=count;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}我们先声明一个图书的对象,然后再模拟一下图书馆存书借书的场景;
// 图书馆class bibliotheca implements Runnable {private Books books;public bibliotheca(Books books) {super();this.books = books;}public Books getBooks() {return books;}public void setBooks(Books books) {this.books = books;}@Overridepublic void run() {books.stockBooks(1000); // 存入1000本书books.taskBooks(1000);System.out.println(Thread.currentThread().getName() + ":"+ books.getNumber());}}
先尝试一下不加锁是什么结果;
public static void main(String[] args) {Books books = new Books("金瓶梅", 1000); // 初始化的时候先存入1000本金瓶梅bibliotheca bibliotheca = new bibliotheca(books); // 把图书注入到图书馆里Thread threads[] = new Thread[10]; // 模拟10个线程for (int i = 0; i < 10; i++) {threads[i] = new Thread(bibliotheca, "Thread" + i);threads[i].start();}}
我运行了5次,发现每次执行完之后每个线程的最终结果都是一样的,比如都是10个1000,或者都是10个2000,包括3000,4000,5000,都有。那么这个结果肯定是不正确的,我们在这个对象上加个锁再试试;
@Overridepublic void run() {synchronized (books) {books.stockBooks(1000); // 存入1000本书books.taskBooks(1000);System.out.println(Thread.currentThread().getName() + ":"+ books.getNumber());}}最终结果都为1000,所以这个才是我们想要的结果;
当多个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。在run方法中我们用了synchronized(books)方法给这个对象加了锁,
当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
@Overridepublic void run() {synchronized (this) {books.stockBooks(1000); // 存入1000本书books.taskBooks(1000);System.out.println(Thread.currentThread().getName() + ":"+ books.getNumber());}}比如上面这样,是不是很常见;或者如下面这样
private byte[] lock = new byte[0]; // 特殊的instance变量 public void method() { synchronized(lock) { // todo 同步代码块 } } public void run() { }
零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
对于静态同步方法,锁是当前类的Class对象。
我们知道静态方法不属于某个对象,而是属于一个具体的类,所以得像下面这样去锁;
class CountThread extends Thread{ private static int count; public CountThread() { count = 0; } public synchronized static void method() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void run() { method(); }}请注意我没有对run方法加同步锁,是因为,我要同步的只是method()这个具体的方法;
public static void main(String[] args) {CountThread countThread=new CountThread();Thread threads[] = new Thread[10]; // 模拟10个线程for (int i = 0; i < 10; i++) {threads[i] = new Thread(countThread, "Thread" + i);threads[i].start();}}现在我们改造一下这个例子:
class CountThread extends Thread{ private static int count; public CountThread() { count = 0; } public synchronized static void method() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void method1() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void run() { method(); method1(); }}run方法里面有method()和method1();这个方法结果是加上同步锁的会保持同步,而没有加上同步锁的则会出现乱数据;
如果我们method()和method1()都没有加上同步,而想让这个两个方法同步怎么办?这就是我们要说的第三种形式;
对于同步方法块,锁是Synchonized括号里配置的对象。
public synchronized void run() { method(); method1(); }当然你也可以这样:
public void run() {synchronized (this) {method();method1();}}是不是很神奇!
写法一修饰的是一个方法,写法二修饰的是一个代码块,但写法一与写法二是等价的,都是锁定了整个方法时的内容。
当一个线程视图访问同步代码块,它首先必须得到锁,退出或抛出异常时必须释放锁,那么锁到底存在哪里?锁里面会存储什么信息啦?请听下次详解啊!
2 1
- Java synchronized的实现原理与应用
- Java中synchronized的实现原理与应用
- Java中synchronized的实现原理与应用
- Java中synchronized的实现原理与应用
- synchronized的实现原理与应用
- Synchronized的实现与原理
- Java多线程中Synchronized的实现原理与优化
- synchronized的实现原理和应用
- synchronized与static synchronized 的区别、synchronized在JVM底层的实现原理及Java多线程锁理解
- synchronized与static synchronized 的区别、synchronized在JVM底层的实现原理及Java多线程锁理解 (r)
- java同步关键字Synchronized 的实现原理
- JAVA synchronized和lock的实现原理
- Java中synchronized的实现原理
- Java的synchronized原理
- Java的synchronized原理
- 并发编程-synchronized的实现原理和应用
- Java锁----Synchronized实现原理
- Java并发机制底层——synchronized的实现原理
- js 数组操作
- 面向对象技术及四性
- 记一次报错(路径方面)
- 第六周书面实践
- Html点击按钮上下逐条滚动,外层div不遮挡内层div内容
- Java synchronized的实现原理与应用
- jsp的基本原理
- 设计模式:中介者模式(Mediator)
- 【追求进步】连续子数组的最大和
- 【ZOJ 1003】 Crashing Balloon
- uva 1103 Ancient Messages
- 补间&属性动画
- javassist学习:对已有类进行字节码操作
- cocos2d: fullPathForFilename: No file found at resource/Player.png. Possible missing file.