锁定老帖子 主题:java线程安全总结
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-06-08
学到了不少东西,对于线程,俺真的。。。。。楼主,做个奶牛呗。加油!!
|
|
返回顶楼 | |
发表时间:2011-06-09
最后修改:2011-06-09
非常不错!
但是感觉Volatile变量为何没有保证原子性没有讲得太清楚。 我个人认为应该是 虽然Volatile保证了可见性,但是n++的过程是不是 只是 read use assign,Volatile只是去除了load store write过程而已,没有了工作内存与主存的同步过程??? |
|
返回顶楼 | |
发表时间:2011-06-09
最后修改:2011-06-09
不过觉得 多线程概念比较多,几个性:
互斥(mutual exclusion)和可见性(visibility) 这里又有了 有序性性 原子性 原子性和有序性有什么区别呢?? 另外当前线程的sleep是可以给其他线程执行时分的,这几个线程之间必须没有锁的竞争。sleep是防止过分无阻塞运算消耗cpu的一个办法 |
|
返回顶楼 | |
发表时间:2011-06-09
不错 收获很大 多谢楼主贡献
|
|
返回顶楼 | |
发表时间:2011-06-10
liwenjie 写道 不过觉得 多线程概念比较多,几个性:
互斥(mutual exclusion)和可见性(visibility) 这里又有了 有序性性 原子性 原子性和有序性有什么区别呢?? 另外当前线程的sleep是可以给其他线程执行时分的,这几个线程之间必须没有锁的竞争。sleep是防止过分无阻塞运算消耗cpu的一个办法 互斥是目的,要达到这个目的,需要从可见性,序性性,原子性入手。 当前线程sleep并没有放弃锁,但是给了CPU执行系统调度的时间,降低us,提升sy,适当的sleep会降低cpu的load。 |
|
返回顶楼 | |
发表时间:2011-06-10
jameswxx 写道
java线程安全总结(二)请看http://www.iteye.com/topic/808550
最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣。已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profile和jvm性能调优 。慢慢写吧。本人jameswxx原创文章,转载请注明出处,我费了很多心血,多谢了。关于java线程安全,网上有很多资料,我只想从自己的角度总结对这方面的考虑,有时候写东西是很痛苦的,知道一些东西,但想用文字说清楚,却不是那么容易。我认为要认识java线程安全,必须了解两个主要的点:java的内存模型,java的线程同步机制。特别是内存模型,java的线程同步机制很大程度上都是基于内存模型而设定的。后面我还会写java并发包的文章,详细总结如何利用java并发包编写高效安全的多线程并发程序。暂时写得比较仓促,后面会慢慢补充完善。 浅谈java内存模型 JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性问题。 for(int i=0;i<10;i++) a++;
public class Account { private int balance; public Account(int balance) { this.balance = balance; } public int getBalance() { return balance; } public void add(int num) { balance = balance + num; } public void withdraw(int num) { balance = balance - num; } public static void main(String[] args) throws InterruptedException { Account account = new Account(1000); Thread a = new Thread(new AddThread(account, 20), "add"); Thread b = new Thread(new WithdrawThread(account, 20), "withdraw"); a.start(); b.start(); a.join(); b.join(); System.out.println(account.getBalance()); } static class AddThread implements Runnable { Account account; int amount; public AddThread(Account account, int amount) { this.account = account; this.amount = amount; } public void run() { for (int i = 0; i < 200000; i++) { account.add(amount); } } } static class WithdrawThread implements Runnable { Account account; int amount; public WithdrawThread(Account account, int amount) { this.account = account; this.amount = amount; } public void run() { for (int i = 0; i < 100000; i++) { account.withdraw(amount); } } } }
synchronized(锁){ 临界区代码 }
public synchronized void add(int num) { balance = balance + num; } public synchronized void withdraw(int num) { balance = balance - num; }
synchronized(锁){ 临界区代码 }
public class ThreadTest{ public void test(){ Object lock=new Object(); synchronized (lock){ //do something } } }
Object lock=new Object();//声明了一个对象作为锁 synchronized (lock) { balance = balance - num; //这里放弃了同步锁,好不容易得到,又放弃了 lock.wait(); }
import java.util.ArrayList; import java.util.List; public class Plate { List<Object> eggs = new ArrayList<Object>(); public synchronized Object getEgg() { if (eggs.size() == 0) { try { wait(); } catch (InterruptedException e) { } } Object egg = eggs.get(0); eggs.clear();// 清空盘子 notify();// 唤醒阻塞队列的某线程到就绪队列 System.out.println("拿到鸡蛋"); return egg; } public synchronized void putEgg(Object egg) { if (eggs.size() > 0) { try { wait(); } catch (InterruptedException e) { } } eggs.add(egg);// 往盘子里放鸡蛋 notify();// 唤醒阻塞队列的某线程到就绪队列 System.out.println("放入鸡蛋"); } static class AddThread extends Thread{ private Plate plate; private Object egg=new Object(); public AddThread(Plate plate){ this.plate=plate; } public void run(){ for(int i=0;i<5;i++){ plate.putEgg(egg); } } } static class GetThread extends Thread{ private Plate plate; public GetThread(Plate plate){ this.plate=plate; } public void run(){ for(int i=0;i<5;i++){ plate.getEgg(); } } } public static void main(String args[]){ try { Plate plate=new Plate(); Thread add=new Thread(new AddThread(plate)); Thread get=new Thread(new GetThread(plate)); add.start(); get.start(); add.join(); get.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("测试结束"); } } 执行结果: 放入鸡蛋 拿到鸡蛋 放入鸡蛋 拿到鸡蛋 放入鸡蛋 拿到鸡蛋 放入鸡蛋 拿到鸡蛋 放入鸡蛋 拿到鸡蛋 测试结束
public class VolatileTest{ public volatile int a; public void add(int count){ a=a+count; } }
public class VolatileTest{ public volatile int a; public void setA(int a){ this.a=a; } }
|
|
返回顶楼 | |
发表时间:2011-06-11
恩好东西,俺会回来仔细学习的
|
|
返回顶楼 | |
发表时间:2011-06-11
楼主列出的这几个方面都是自己最近要学习的,有些也看了一段时间了,比如内存模型,恕我直言,楼主关于内存模型的内容是自己写的么?我貌似什么地方看过,当时看的时候就有点模糊,希望楼主能通俗解释一下,在此先谢过!
|
|
返回顶楼 | |
发表时间:2011-06-12
受益匪浅,期待更多精彩
|
|
返回顶楼 | |
发表时间:2011-06-12
xyz317100759 写道
jameswxx 写道
java线程安全总结(二)请看http://www.iteye.com/topic/808550
最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣。已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profile和jvm性能调优 。慢慢写吧。本人jameswxx原创文章,转载请注明出处,我费了很多心血,多谢了。关于java线程安全,网上有很多资料,我只想从自己的角度总结对这方面的考虑,有时候写东西是很痛苦的,知道一些东西,但想用文字说清楚,却不是那么容易。我认为要认识java线程安全,必须了解两个主要的点:java的内存模型,java的线程同步机制。特别是内存模型,java的线程同步机制很大程度上都是基于内存模型而设定的。后面我还会写java并发包的文章,详细总结如何利用java并发包编写高效安全的多线程并发程序。暂时写得比较仓促,后面会慢慢补充完善。 浅谈java内存模型 JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性问题。 for(int i=0;i<10;i++) a++;
public class Account { private int balance; public Account(int balance) { this.balance = balance; } public int getBalance() { return balance; } public void add(int num) { balance = balance + num; } public void withdraw(int num) { balance = balance - num; } public static void main(String[] args) throws InterruptedException { Account account = new Account(1000); Thread a = new Thread(new AddThread(account, 20), "add"); Thread b = new Thread(new WithdrawThread(account, 20), "withdraw"); a.start(); b.start(); a.join(); b.join(); System.out.println(account.getBalance()); } static class AddThread implements Runnable { Account account; int amount; public AddThread(Account account, int amount) { this.account = account; this.amount = amount; } public void run() { for (int i = 0; i < 200000; i++) { account.add(amount); } } } static class WithdrawThread implements Runnable { Account account; int amount; public WithdrawThread(Account account, int amount) { this.account = account; this.amount = amount; } public void run() { for (int i = 0; i < 100000; i++) { account.withdraw(amount); } } } }
synchronized(锁){ 临界区代码 }
public synchronized void add(int num) { balance = balance + num; } public synchronized void withdraw(int num) { balance = balance - num; }
synchronized(锁){ 临界区代码 }
public class ThreadTest{ public void test(){ Object lock=new Object(); synchronized (lock){ //do something } } }
Object lock=new Object();//声明了一个对象作为锁 synchronized (lock) { balance = balance - num; //这里放弃了同步锁,好不容易得到,又放弃了 lock.wait(); }
import java.util.ArrayList; import java.util.List; public class Plate { List<Object> eggs = new ArrayList<Object>(); public synchronized Object getEgg() { if (eggs.size() == 0) { try { wait(); } catch (InterruptedException e) { } } Object egg = eggs.get(0); eggs.clear();// 清空盘子 notify();// 唤醒阻塞队列的某线程到就绪队列 System.out.println("拿到鸡蛋"); return egg; } public synchronized void putEgg(Object egg) { if (eggs.size() > 0) { try { wait(); } catch (InterruptedException e) { } } eggs.add(egg);// 往盘子里放鸡蛋 notify();// 唤醒阻塞队列的某线程到就绪队列 System.out.println("放入鸡蛋"); } LZ这个太不靠谱了 判断条件居然用的是if
|
|
返回顶楼 | |