对象变量的并发访问

前言:本系列将从零开始讲解java多线程相关的技术,内容参考于《java多线程核心技术》与《java并发编程实战》等相关资料,希望站在巨人的肩膀上,再通过我的理解能让知识更加简单易懂。

目录

线程安全

  • 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

局部变量并不会数据共享

  1. public class T1 {
  2. public static void main(String[] args) {
  3. PrivateNum p=new PrivateNum();
  4. MyThread threadA=new MyThread('A',p);
  5. MyThread threadB=new MyThread('B',p);
  6. threadA.start();
  7. threadB.start();
  8. }}
  9. class MyThread extends Thread
  10. {
  11. char i;
  12. PrivateNum p;
  13. public MyThread(char i,PrivateNum p)
  14. {
  15. this.i=i;
  16. this.p=p;
  17. }
  18. public void run()
  19. {
  20. p.test(i);
  21. }
  22. }
  23. class PrivateNum
  24. {
  25. public void test( char i)
  26. {
  27. try {
  28. int num=0;
  29. if(i=='A')
  30. {
  31. num=100;
  32. System.out.println("线程A已经设置完毕");
  33. Thread.sleep(1000);
  34. }
  35. else
  36. {
  37. num=200;
  38. System.out.println("线程B已经设置完毕");
  39. }
  40. System.out.println("线程"+i+"的值:"+num);
  41. }
  42. catch (InterruptedException e) {
  43. // TODO 自动生成的 catch 块
  44. e.printStackTrace();
  45. }}
  46. }
  47. 线程A已经设置完毕
  48. 线程B已经设置完毕
  49. 线程B的值:200
  50. 线程A的值:100
  • 在这段代码中,线程A和B先后对num进行赋值,当两个线程都赋值后再分别打印,但是输出的结果并不相同,后赋值的线程并没有对num的值进行覆盖,因为这里的num是在方法里面的,也就是局部变量,不同线程的num并不共享,所以并不会发生覆盖。

实例成员变量数据共享

  1. public void test( char i)
  2. {
  3. int num=0;
  4. try {
  5. if(i=='A')
  6. {
  7. num=100;
  8. System.out.println("线程A已经设置完毕");
  9. Thread.sleep(1000);
  10. }
  11. else
  12. {
  13. num=200;
  14. System.out.println("线程B已经设置完毕");
  15. }
  16. System.out.println("线程"+i+"的值:"+num);
  17. }
  18. catch (InterruptedException e) {
  19. // TODO 自动生成的 catch 块
  20. e.printStackTrace();
  21. }}
  22. 线程B已经设置完毕
  23. 线程A已经设置完毕
  24. 线程B的值:200
  25. 线程A的值:200
  • 这里的代码只是将int num=0放到了方法的外面,但是输出的结果却不同,因为这时候线程AB访问的是同一个变量(指向同一个地址),所以这个时候会发生覆盖,同时这里出现了线程安全问题。

synchronized关键字可以避免线程安全问题

  1. public synchronized void test( char i)
  2. {
  3. int num=0;
  4. try {
  5. if(i=='A')
  6. {
  7. num=100;
  8. System.out.println("线程A已经设置完毕");
  9. Thread.sleep(1000);
  10. }
  11. else
  12. {
  13. num=200;
  14. System.out.println("线程B已经设置完毕");
  15. }
  16. System.out.println("线程"+i+"的值:"+num);
  17. }
  18. catch (InterruptedException e) {
  19. // TODO 自动生成的 catch 块
  20. e.printStackTrace();
  21. }}
  22. 线程A已经设置完毕
  23. 线程A的值:100
  24. 线程B已经设置完毕
  25. 线程B的值:200
  • 这里只是上面代码的基础上增加了一个synchronized ,避免了线程安全问题

总结

  • 如果多个线程访问的是同一个对象方法中的局部变量,那么这个变量并不共享,线程AB对此变量的操作将互不影响
  • 如果多个线程访问的是同一个对象方法中的成员变量,那么这个变量共享,如果不处理好线程问题,可能会出现线程安全问题
  • 通过synchronized关键字可以使方法同步

多个线程访问的是两个不同实例的同一个同步方法

  1. public class T1 {
  2. public static void main(String[] args) {
  3. PrivateNum p1=new PrivateNum();
  4. PrivateNum p2=new PrivateNum();
  5. MyThread threadA=new MyThread('A',p1);
  6. MyThread threadB=new MyThread('B',p2);
  7. threadA.start();
  8. threadB.start();
  9. }}
  10. 线程A已经设置完毕
  11. 线程B已经设置完毕
  12. 线程B的值:200
  13. 线程A的值:100
  • 这里的代码又是在上面的代码进行修改,这里我们添加了synchronized关键字,对方法上锁,但是却是异步执行的(同步的话,应该是这样输出 线程A已经设置完毕 线程A的值:100 ),这是因为这里是两个锁,创建了p1和p2对象,创建的是两个锁,锁对象不同不造成互斥作用。

多线程调用同一个实例的两个不同(一个同步,一个非同步)方法

  1. public class T1 {
  2. public static void main(String[] args) {
  3. PrivateNum p1=new PrivateNum();
  4. MyThread threadA=new MyThread('A',p1);
  5. MyThread2 threadB=new MyThread2('B',p1);
  6. threadA.start();
  7. threadB.start();
  8. }}
  9. class MyThread extends Thread
  10. {
  11. char i;
  12. PrivateNum p;
  13. public MyThread(char i,PrivateNum p)
  14. {
  15. this.i=i;
  16. this.p=p;
  17. }
  18. public void run()
  19. {
  20. p.test(i);
  21. }
  22. }
  23. class MyThread2 extends Thread
  24. {
  25. char i;
  26. PrivateNum p;
  27. public MyThread2(char i,PrivateNum p)
  28. {
  29. this.i=i;
  30. this.p=p;
  31. }
  32. public void run()
  33. {
  34. p.test2(i);
  35. }
  36. }
  37. class PrivateNum
  38. {
  39. int num=0;
  40. public void test2(char i)
  41. {
  42. System.out.println("线程"+i+"执行,线程A并没有同步执行");
  43. }
  44. public synchronized void test( char i)
  45. {
  46. try {
  47. if(i=='A')
  48. {
  49. num=100;
  50. System.out.println("线程A已经设置完毕");
  51. Thread.sleep(100);
  52. }
  53. else
  54. {
  55. num=200;
  56. System.out.println("线程B已经设置完毕");
  57. }
  58. System.out.println("线程"+i+"的值:"+num);
  59. }
  60. catch (InterruptedException e) {
  61. // TODO 自动生成的 catch 块
  62. e.printStackTrace();
  63. }}
  64. }
  65. 线程A已经设置完毕
  66. 线程B执行,线程A并没有同步执行
  67. 线程A的值:100
  68. 线程B的值:200
  • 这里的代码我们给PrivateNum添加了一个非同步的test2方法,MyThreadrun中调用的同步的test方法,MyThread2中调用的是非同步的test2方法,实验表明线程B可以异步调用非同步的方法。

多线程调用同一个实例的两个不同的同步方法

  1. public synchronized void test2(char i)
  2. {
  3. System.out.println("线程"+i+"执行,线程A同步执行");
  4. }
  5. 线程A已经设置完毕
  6. 线程A的值:100
  7. 线程B执行,线程A同步执行
  8. 线程B的值:200
  • 这里的代码我们只是给test2方法添加一个synchronized关键字,这个时候两个线程调用的方法同步执行。

总结

  • 多个线程调用的不同实例的同步方法,线程不互斥。
  • 如果两个线程的锁对象一样(都是p1),两个线程分别调用同步方法和非同步方法,线程不会同步执行。
  • 但是如果调用两个不同的同步方法,因为锁对象一致,两个线程同步执行。
  • 设想一个情况,有一个实例有两个方法,一个修改值(synchronized),一个读值(非synchronized),此时两个线程一个修改值,一个读取值,这个时候因为这两个线程并不会挣抢锁,两个线程互不影响,那么此时可能就会出现一种情况,线程A还没修改完,线程B就读取到没有修改的值。这就是所谓的脏读。

重入锁

  1. public class T1 {
  2. public static void main(String[] args) {
  3. MyThread3 thread=new MyThread3();
  4. thread.start();
  5. }}
  6. class MyThread3 extends Thread
  7. {
  8. Service s=new Service();
  9. public void run()
  10. {
  11. s.service1();
  12. }
  13. }
  14. class Service
  15. {
  16. public synchronized void service1()
  17. {
  18. System.out.println("服务1并没有被锁住");
  19. service2();
  20. }
  21. public synchronized void service2()
  22. {
  23. System.out.println("服务2并没有被锁住");
  24. service3();
  25. }
  26. public synchronized void service3()
  27. {
  28. System.out.println("服务3并没有被锁住");
  29. }
  30. }
  31. 服务1并没有被锁住
  32. 服务2并没有被锁住
  33. 服务3并没有被锁住
  • 我们可能会这么认为,thread线程执行了同步的service1方法,这个时候把锁占住,如果这个时候要执行另一个同步方法service2方法,必须先执行完service1方法,然后把锁让出去才行,但是实验证明锁是可以重入的,一个线程获得锁后,还没释放后可以再次获取锁。

出现异常会释放锁

  • 如果同步方法里面出现异常,会自动将锁释放

同步方法不会继承

  1. public class T1 {
  2. public static void main(String[] args) {
  3. Service3 s=new Service3();
  4. MyThread4 t1=new MyThread4(s,'1');
  5. MyThread4 t2=new MyThread4(s,'2');
  6. t1.start();
  7. t2.start();
  8. }}
  9. class MyThread4 extends Thread
  10. {
  11. Service3 s;
  12. char name;
  13. public MyThread4(Service3 s,char name)
  14. {
  15. this.s=s;
  16. this.name=name;
  17. }
  18. public void run()
  19. {
  20. s.service(name);
  21. }
  22. }
  23. class Service2
  24. {
  25. public synchronized void service(char name)
  26. {
  27. for (int i = 3; i >0; i--) {
  28. System.out.println(i);
  29. }
  30. }
  31. }
  32. class Service3 extends Service2
  33. {
  34. public void service(char name)
  35. {
  36. for (int i = 5; i >0; i--) {
  37. System.out.println("线程"+name+":"+i);
  38. }
  39. }
  40. }
  41. 线程1:5 线程2:5
  • 如果父类的方法是同步的,如果子类重载同步方法,但是没有synchronized关键字,那么是没有同步作用的。

总结

  • 重入锁,一个获得的锁的线程没执行完可以继续获得锁。
  • 线程占用锁的时候,如果执行的同步出现异常,会将锁让出。
  • 父类方法同步,子类重写该方法(没有synchronized关键字修饰),是没有同步作用的。

同步代码块

  1. public class T1 {
  2. public static void main(String[] args) {
  3. Service2 s=new Service2();
  4. MyThread t1=new MyThread(s,'A');
  5. MyThread t2=new MyThread(s,'B');
  6. t1.start();
  7. t2.start();
  8. }
  9. }
  10. class Service2
  11. {
  12. public void service(char name)
  13. {
  14. synchronized(this)
  15. {
  16. for (int i = 3; i >0; i--) {
  17. System.out.println(name+":"+i);
  18. }
  19. }
  20. }
  21. }
  22. class MyThread extends Thread
  23. {
  24. Service2 s=new Service2();
  25. char name;
  26. public MyThread(Service2 s,char name)
  27. {
  28. this.s=s;
  29. this.name=name;
  30. }
  31. public void run()
  32. {
  33. s.service(name);
  34. }
  35. }
  36. A:3
  37. A:2
  38. A:1
  39. B:3
  40. B:2
  41. B:1
  • 当多个线程访问同一个对象的synchronized(this)代码块时,一段时间内只有一个线程能执行

同步代码块的锁对象

  1. class Service2
  2. {
  3. String s=new String("锁");
  4. public void service(char name)
  5. {
  6. synchronized(s)
  7. {
  8. for (int i = 3; i >0; i--) {
  9. System.out.println(name+":"+i);
  10. }
  11. }
  12. }
  13. }
  • 将this换成自己创建的锁(一个对象),同样可以实现同步功能

部分同步,部分异步

  1. public void service(char name)
  2. {
  3. for (int i = 6; i >3; i--) {
  4. System.out.println(name+":"+i);
  5. }
  6. synchronized(this)
  7. {
  8. for (int i = 3; i >0; i--) {
  9. System.out.println(name+":"+i);
  10. }
  11. }
  12. }
  13. A:6
  14. B:6
  15. A:5
  16. B:5
  17. A:4
  18. B:4
  19. A:3
  20. A:2
  21. A:1
  22. B:3
  23. B:2
  24. B:1
  • 不在同步代码块中的代码可以异步执行,在同步代码块中的代码同步执行

不同方法里面的synchronized代码块同步执行

  1. public class T1 {
  2. public static void main(String[] args) {
  3. Service2 s=new Service2();
  4. MyThread t1=new MyThread(s,'A');
  5. MyThread2 t2=new MyThread2(s,'B');
  6. t1.start();
  7. t2.start();
  8. }
  9. }
  10. class Service2
  11. {
  12. public void service(char name)
  13. {
  14. synchronized(this)
  15. {
  16. for (int i = 3; i >0; i--) {
  17. System.out.println(name+":"+i);
  18. }
  19. }
  20. }
  21. public void service2(char name)
  22. {
  23. synchronized(this) {
  24. for (int i = 6; i >3; i--) {
  25. System.out.println(name+":"+i);
  26. }
  27. }
  28. }
  29. }
  30. class MyThread extends Thread
  31. {
  32. Service2 s=new Service2();
  33. char name;
  34. public MyThread(Service2 s,char name)
  35. {
  36. this.s=s;
  37. this.name=name;
  38. }
  39. public void run()
  40. {
  41. s.service(name);
  42. }
  43. }
  44. class MyThread2 extends Thread
  45. {
  46. Service2 s=new Service2();
  47. char name;
  48. public MyThread2(Service2 s,char name)
  49. {
  50. this.s=s;
  51. this.name=name;
  52. }
  53. public void run()
  54. {
  55. s.service2(name);
  56. }
  57. }
  58. A:3
  59. A:2
  60. A:1
  61. B:6
  62. B:5
  63. B:4
  • 两个线程访问同一个对象的两个同步代码块,这两个代码块是同步执行的

锁不同没有互斥作用

  1. class Service2
  2. {
  3. Strign s=new String();
  4. public void service(char name)
  5. {
  6. synchronized(s)
  7. {
  8. for (int i = 3; i >0; i--) {
  9. System.out.println(name+":"+i);
  10. }
  11. }
  12. }
  13. public void service2(char name)
  14. {
  15. synchronized(this) {
  16. for (int i = 6; i >3; i--) {
  17. System.out.println(name+":"+i);
  18. }
  19. }
  20. }
  21. }
  • 将this改成s,也就是改变锁对象,发现两个方法并不是同步执行的

synchronized方法和synchronized(this)代码块是锁定当前对象的

  1. public void service(char name)
  2. {
  3. synchronized(this)
  4. {
  5. for (int i = 3; i >0; i--) {
  6. System.out.println(name+":"+i);
  7. }
  8. }
  9. }
  10. public synchronized void service2(char name)
  11. {
  12. for (int i = 6; i >3; i--) {
  13. System.out.println(name+":"+i);
  14. }
  15. }
  • 将service2的代码块改成synchronized 方法,发现输出结果是同步的的,说明锁定的都是当前对象

总结

  • 同步代码块的锁对象可以是本对象,也可以是其他对象。同一个锁对象可以产生互斥作用,不同锁对象不能产生互斥作用
  • 一个方法中有同步代码块和非同步代码块,同步代码块的代码是同步执行的(块里的代码一次执行完),而非同步代码块的代码可以异步执行
  • 一个对象中的不同同步代码块是互斥的,执行完一个代码块再执行另一个代码块
  • 同步代码块(this)和synchronized方法的锁定的都是当前对象 this

syncronized static 同步静态方法

  1. class Service2
  2. {
  3. public synchronized static void service()
  4. {
  5. for (int i = 3; i >0; i--) {
  6. System.out.println(name+":"+i);
  7. }
  8. }
  9. }
  • 在这里锁对象就不是service对象,而是Class(Class(和String Integer一样)是一个类)

Class锁

  1. class Service2
  2. {
  3. public static void service()
  4. {
  5. synchronized(Service.class)
  6. {
  7. for (int i = 3; i >0; i--) {
  8. System.out.println(name+":"+i);
  9. }
  10. }
  11. }
  12. }
  • 这里的效果和上面静态的synchronized一样

静态类中非静态同步方法

  1. public class T1 {
  2. public static void main(String[] args) {
  3. Service.Service2 s=new Service.Service2();
  4. Thread t1=new Thread(new Runnable()
  5. {public void run(){s.service();}});
  6. Thread t2=new Thread(new Runnable()
  7. {public void run(){Service.Service2.service2();}});
  8. t1.start();
  9. t2.start();
  10. }
  11. }
  12. class Service{
  13. static class Service2
  14. {
  15. public synchronized void service()
  16. {
  17. for (int i = 20; i >10; i--) {
  18. System.out.println(i);
  19. }
  20. }
  21. public static synchronized void service2()
  22. {
  23. for (int i = 9; i >3; i--) {
  24. System.out.println(i);
  25. }
  26. }
  27. }}
  28. //不同步执行
  • 这里service方法的锁还是service对象,

总结

  • Class类也可以是锁,Class锁的实现可以通过静态的synchronizd方法,也可以通过静态方法里面的同步代码块(锁对象为Class)
  • 静态类的同步方法锁对象还是该类的一个实例

死锁

  1. public class DealThread implements Runnable {
  2. public String username;
  3. public Object lock1 = new Object();
  4. public Object lock2 = new Object();
  5. public void setFlag(String username) {
  6. this.username = username;
  7. }
  8. @Override
  9. public void run() {
  10. if (username.equals("a")) {
  11. synchronized (lock1) {
  12. try {
  13. System.out.println("username = " + username);
  14. Thread.sleep(3000);
  15. } catch (InterruptedException e) {
  16. // TODO Auto-generated catch block
  17. e.printStackTrace();
  18. }
  19. synchronized (lock2) {
  20. System.out.println("按lock1->lock2代码顺序执行了");
  21. }
  22. }
  23. }
  24. if (username.equals("b")) {
  25. synchronized (lock2) {
  26. try {
  27. System.out.println("username = " + username);
  28. Thread.sleep(3000);
  29. } catch (InterruptedException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. }
  33. synchronized (lock1) {
  34. System.out.println("按lock2->lock1代码顺序执行了");
  35. }
  36. }
  37. }
  38. }
  39. }
  • 线程AB开始执行时,因为锁不同,所以不互斥,A当执行到另一个同步代码块(锁2)的时候,由于这个时候锁给线程B占有了,所以只能等待,同样B线程也是如此,AB互相抢对方的锁,但是所以造成了死锁。

锁对象发生改变

  • 修改锁对象的属性不印象结果,比如此时锁对象为user对象,我把user的name设为jiajun,此时不影响结果

volatile

  1. public class Tee {
  2. public static void main(String[] args) {
  3. try {
  4. RunThread thread = new RunThread();
  5. thread.start();
  6. Thread.sleep(1000);
  7. thread.setRunning(false);
  8. System.out.println("已经赋值为false");
  9. } catch (InterruptedException e) {
  10. // TODO Auto-generated catch block
  11. e.printStackTrace();
  12. }
  13. }
  14. }
  15. class RunThread extends Thread {
  16. private boolean isRunning = true;
  17. public boolean isRunning() {
  18. return isRunning;
  19. }
  20. public void setRunning(boolean isRunning) {
  21. this.isRunning = isRunning;
  22. }
  23. @Override
  24. public void run() {
  25. System.out.println("进入run了");
  26. while (isRunning == true) {
  27. }
  28. System.out.println("线程被停止了!");
  29. }
  30. }
  • 在这里,把vm运行参数设置为-server(右键运行配置,自变量那里可以设置,server参数可以提高运行性能),结果发现虽然我们将值设置为false,但是却仍然进入死循环。
  • isRunning变量存放在公共堆栈和线程的私有堆栈中,我们对他赋值为false时,只对公共堆栈进行更新,而但我们设置为-server后,读取的是线程私有栈的内容,所以也就造成了死循环。我们可以在isRunning变量前加上volatite关键字,这个时候访问的是公共堆栈,就不会造成死循环了。
  • 以前我们使用单线程的时候,这种情况情况不会发生,但是当多个线程进行读写操作的时候就可能爆发出问题,这是因为我们没有用同步机制来保证他,这是我们需要注意的一点。
  1. public class Tee {
  2. public static void main(String[] args) {
  3. MyThread[] mythreadArray = new MyThread[100];
  4. for (int i = 0; i < 100; i++) {
  5. mythreadArray[i] = new MyThread();
  6. }
  7. for (int i = 0; i < 100; i++) {
  8. mythreadArray[i].start();
  9. }
  10. }
  11. class MyThread extends Thread {
  12. volatile public static int count;
  13. private static void addCount() {
  14. for (int i = 0; i < 100; i++) {
  15. count++;
  16. }
  17. System.out.println("count=" + count);
  18. }
  19. @Override
  20. public void run() {
  21. addCount();
  22. }
  23. }
  • 在这里我们只count前添加volatile,但是最终结果输出的并不是10000,说明并没有同步的作用,volatile不处理数据原子性(i++不是原子操作)
  • 我们将volatile去掉,将addcount方法用synchronized修饰,发现输出了10000,说明了synchronized的同步作用不仅保证了对同一个锁线程的互斥,还保证了数据的同步。

总结

  • volitate增加了实例变量在对个线程之间的可见性,保证我们获得的是变量的最新值。
  • volatile在读上面保持了同步作用,但是在写上面不保持同步
  • synchronized的同步作用不仅保证了对同一个锁线程的互斥,还保证了数据的同步

volatile对比synchronized

  • 两者修饰的不同,volatile修饰的是变量,synchronized修饰的是方法和代码块
  • 两者的功能不同。volatile保证数据的可见性,synchronized是线程同步执行(间接保证数据可见性,让线程工作内存的变量和公共内存的同步)
  • volatile性能比synchronized性能高

用原子类实现i++同步

  1. class MyThread extends Thread {
  2. static AtomicInteger count=new AtomicInteger(0);
  3. private static void addCount() {
  4. for (int i = 0; i < 100; i++) {
  5. count.incrementAndGet();
  6. }
  7. System.out.println(count.get());
  8. }
  9. @Override
  10. public void run() {
  11. addCount();
  12. }
  13. }
  • 将上面的count++进行用原子类AtomicInteger改变,最后输出了1000

我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

作者:jiajun 出处: http://www.cnblogs.com/-new/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

java多线程系列(二)的更多相关文章

  1. java多线程系列(二)---对象变量并发访问

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  2. (Java多线程系列二)线程间同步

    Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...

  3. Java多线程系列二——Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...

  4. 【Java多线程系列二】Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法. /* * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机会,它自己也有可能再次得到执行机会 */ public s ...

  5. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  6. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  7. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  8. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  9. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

随机推荐

  1. haproxy内存管理-free_list原理

    haproxy的内存管理中,通过pool_head->free_list,存储空闲内存块,free_list是个二级指针,却把空闲内存块都串了起来,没有用next,pre之类的指针.怎么实现的? ...

  2. Js实现京东无延迟菜单效果(demo)

    一个端午节,外面人山人海,又那么热,我认为宅在家里看看慕课网,充实自己来的实际... 这是一个js实现京东无延迟菜单效果,感觉很好,分享给大家... 1.开发基本的菜单结构 2.开发普通的二级菜单效果 ...

  3. 香港科技大学的VINS_MONO初试

    简介 VINS-Mono 是香港科技大学开源的一个VIO,我简单的测试了,发现效果不错.做个简单的笔记,详细的内容等我毕设搞完再弄. 代码主要分为前端(feature tracker),后端(slid ...

  4. CSS小技巧-为内盒子添加margin-top时,会带着父盒子一起下来,如何解决?

    1.为父盒子添加一个padding 2.为父盒子添加一个border 3.为父盒子添加一个overflow:hidden

  5. (转)Java 读写Properties配置文件

    原文:http://www.cnblogs.com/xudong-bupt/p/3758136.html 1.Properties类与Properties配置文件 Properties类继承自Hash ...

  6. poj2069

    poj2069 题意 求一个覆盖所有点的最小球体的半径.即求空间内一点到所有点的距离的最大值最小的点. 分析 模拟退火算法,但这道题竟然不用随机函数就能过了,主要体现了算法的渐近收敛性, 起始点随意取 ...

  7. Centos 执行shell命令返回127错误

    shell脚本功能:连接mysql,自动创建数据库,脚本如下 mysql -h$MYSQL_IP -u$MYSQL_USER -p$MYSQL_PASSWORD --default-character ...

  8. Asp.Net页面传值的方法简单总结【原创】

    1.QueryString 当页面上form按照get的方式向页面发送请求数据的时候,web server会将请求数据放入 一个QEURY_STRING的环境变量中,然后通过QeueryString方 ...

  9. div+css的属性

    div+css的属性 gCascading Style Sheet 层叠式样式表 ==> 层叠样式表 Internal Style Sheet 内部样式表 External Style Shee ...

  10. ipython及Python初体验

    阅读目录: Python环境体验 Python编辑器 ipython安装 Python提示符 Python初体验 print和变量 变量操作 内建函数:方法 数学运算:简单算术.随机数 关于模块 一. ...