java学习(synchronized)
2016-12-10 22:52
267 查看
synchronized关键字
作用:1. 修饰代码块,被修饰的代码块称为同步语句块,其作用范围是{}括起来的代码,作用的对象是调用这个代码块的对象
2. 修饰非静态方法,被修饰的方法称为同步方法,其作用范围是整个方法,作用的对象是调用这个方法的对象
3. 修饰静态方法,其作用范围是整个静态方法,作用的对象是这个类所有的对象
4. 修饰类,其作用的范围是synchronized后面括起来的部分,作用的对象是这个类的所有对象
对代码块加锁
代码public class ThreadSynchronize implements Runnable { public void run() { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "synchronized loop" + i); } } } public static void main(String[] args) { ThreadSynchronize t1 = new ThreadSynchronize(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } }
结果
Asynchronized loop0 Asynchronized loop1 Asynchronized loop2 Asynchronized loop3 Asynchronized loop4 Bsynchronized loop0 Bsynchronized loop1 Bsynchronized loop2 Bsynchronized loop3 Bsynchronized loop4
由代码可以得出结论:当两个并发进程访问同一个对象的由synchronized (this)修饰地代码块时,一次只能有一个线程得到这个代码块,另一个必须等待
注意:是两个线程访问同一个对象的,同一个对象的,同一个对象的!
将main函数改为如下如下代码:
ThreadSynchronize t1 = new ThreadSynchronize(); ThreadSynchronize t2 = new ThreadSynchronize(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t2, "B"); ta.start(); tb.start();
得到结果
Asynchronized loop0 Bsynchronized loop0 Asynchronized loop1 Bsynchronized loop1 Asynchronized loop2 Asynchronized loop3 Bsynchronized loop2 Asynchronized loop4 Bsynchronized loop3 Bsynchronized loop4
也就是说,当不同线程要访问不同对象的同一个代码块时,synchronized不会起到阻塞效果
代码
public class ThreadSynchronize { public void m4t1() { synchronized (this) { int i = 5; while(i-- > 0){ System.out.println(Thread.currentThread().getName() + ": " + i); try{ Thread.sleep(500); }catch(InterruptedException ie){ } } } } public void m4t2(){ int i =5; while(i-- > 0){ System.out.println(Thread.currentThread().getName() + ": " + i); try{ Thread.sleep(500); }catch(InterruptedException ie){ } } } public static void main(String[] args) { ThreadSynchronize t1 = new ThreadSynchronize(); Thread ta = new Thread(new Runnable() { @Override public void run() { t1.m4t1(); } },"ta"); Thread tb = new Thread(new Runnable() { @Override public void run() { t1.m4t2(); } },"tb"); ta.start(); tb.start(); } }
结果
tb: 4 ta: 4 tb: 3 ta: 3 ta: 2 tb: 2 ta: 1 tb: 1 tb: 0 ta: 0
结果表明:当一个线程访问一个对象的synchronized(this) 代码块时,另一个线程可以访问该对象的非synchronized(this) 修饰的代码块(不同函数中的)
将m4t2()修改得与m4t1()相同,即都用synchronized(this)修饰后,得到结果
ta: 4 ta: 3 ta: 2 ta: 1 ta: 0 tb: 4 tb: 3 tb: 2 tb: 1 tb: 0
结果表明:当一个线程访问到了一个对象的synchronized(this)修饰的代码块时,其他所有线程对该对象的synchronized(this)修饰的代码块的访问都会被阻塞,此时称该线程获取了该对象的对象锁,使得其他线程都不能在此时访问同步代码块
对指定某个对象加锁
public class ThreadSynchronize { public static void main(String[] args) { Account account = new Account("zhangsan", 10000); AccountOperator accountOperator = new AccountOperator(account); final int THREAD_NUM = 5; Thread[] threads = new Thread[THREAD_NUM]; for (int i = 0; i < THREAD_NUM; i++) { threads[i] = new Thread(accountOperator, "Thread" + i); threads[i].start(); } } } class Account { String name; float amount; public Account(String name, float amount) { this.name = name; this.amount = amount; } public void deposit(float amt) { amount += amt; try{ Thread.sleep(100); } catch (InterruptedException e){ } } public void withdraw(float amt) { amount -= amt; try { Thread.sleep(100); } catch(InterruptedException e){ } } public float get() { return amount; } } class AccountOperator implements Runnable { private Account account; public AccountOperator(Account account) { this.account = account; } @Override public void run() { // TODO Auto-generated method stub synchronized(account){ account.deposit(500); account.withdraw(300); System.out.println(Thread.currentThread().getName() + " : " + account.get()); } } }
输出结果
Thread0 : 10200.0 Thread3 : 10400.0 Thread4 : 10600.0 Thread2 : 10800.0 Thread1 : 11000.0
在run方法里,我们用synchronized给account对象加了锁,此时,其他想要访问也对account加了锁的区域的线程将会被阻塞
修饰一个非静态方法
public synchronized void run() { // TODO Auto-generated method stub account.deposit(500); account.withdraw(300); System.out.println(Thread.currentThread().getName() + " : " + account.get()); }
表示该方法一次只能让一个对象调用,与之前一个表示方式等价
修饰静态方法
很明显,静态方法是属于类的,因此,静态方法可以保证同一个类的不同实例之间保持同步public class ThreadSynchronize implements Runnable { public void run() { method(); } public static synchronized void method(){ for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "synchronized loop" + i); } } public static void main(String[] args) { ThreadSynchronize t1 = new ThreadSynchronize(); ThreadSynchronize t2 = new ThreadSynchronize(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t2, "B"); ta.start(); tb.start(); } }
输出结果为
Asynchronized loop0 Asynchronized loop1 Asynchronized loop2 Asynchronized loop3 Asynchronized loop4 Bsynchronized loop0 Bsynchronized loop1 Bsynchronized loop2 Bsynchronized loop3 Bsynchronized loop4
修饰一个类
很明显,修饰一个类的时候,该类的所有实例公用同一把锁参考:http://blog.csdn.net/luoweifu/article/details/46613015
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Debian 7.x 安装Oracle JAVA
- springmvc实现url路由功能
- spring boot 配置 druid/** * 配置druid * Created by adam on 4/11/16. */ @Configuration public class D
- api接口rsa加密
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解