当前位置:编程学习 > JAVA >>

Java并发编程实战

1.同步包括两方面:原子性和可见性。
http://bbs.itheima.com/thread-23776-1-1.html?fstgj以前的学习网站,需要的自己看下,可以去这个网站下载,下载视频免费,不需要注册和做什么任务。
2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据。

Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的long和double变量,JVM允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用关键字volatile来声明它们,或者用锁保护起来。
加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步。
下面的代码是书中例子,如果多线程访问这个类,就存在可见性问题,但是如何测试得到比如输出为0的结果或者程序无法终止?求赐教!

public class NoVisibility {
    
    private static boolean ready = false;
    private static int number = 0;

    public static class ReaderThread extends Thread {
        public void run() {
            while (!ready) {
                Thread.yield();
            }
            System.out.println(number);   //如何测试输出0呢?
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new ReaderThread().start();
        number = 42;
        ready = true;
    }
}

 

3.volatile变量:用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。
当且仅当满足以下所有条件时,才应该使用volatile变量:
对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。   
该变量不会与其他状态变量一起纳入不变性条件中。   
在访问变量时不需要加锁。
4.线程封闭:当访问共享的可变数据,通常需要使用同步。一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据,就不需要同步。这种技术被称为线程封闭

三种方式实现:

Ad-hoc线程封闭
栈封闭
ThreadLocal类
5.不变性:不可变对象一定是线程安全的。

  当满足一下条件时,对象才是不可变的:

  对象创建以后其状态就不能修改。
  对象的所有域都是final类型。
  对象是正确创建的(在对象的创建期间,this引用没有逸出)。
6. 下面这个Holder类是“未被正确发布”,它存在两个问题,首先,除了发布对象的线程外,其他线程可以看到的Holder域是一个失效值,因此将看到一个空引用或者之前的旧值,然而,更糟糕的情况是,线程看到Holder引用的值是最新的,但Holder状态的值却是失效的。情况变得更加不可预测的是,某个线程在第一次读取域时得到失效值,而再次读取这个域时会得到一个更新值,这也是assertSainty抛出AssertionError的原因。我想知道如何测试,能抛出AssertionError异常来。


public class Holder {

    private int n;

    public Holder(int n) throws InterruptedException {
        this.n = n;
    }

    public void assertSanity() {
        if (n != n) {
            throw new AssertionError("This statement is false");   //如何测试抛出该异常?
        }
    }
    
} 编程 Java 并发 多线程 测试 --------------------编程问答-------------------- --------------------编程问答-------------------- 虽然是软文,还是回复下:http://ifeve.com/concurrency-visibility/ --------------------编程问答-------------------- public class Test implements Runnable{

// 不安全发布:有个线程一直读取这个对象试试
public Holder holder;

public void initialize() {
    holder = new Holder(42);
}

        /**
         * @param args
         */
        public static void main(String[] args) {
                Test t = new Test();
                (new Thread(t)).start();
                t.initialize();
               
        }

        @Override
        public void run() {
  try
{
                  Thread.sleep(0);  // 可以休眠数秒让t.initialize();完成初始化
}
                catch(Exception e)
          {}
                
                
                while(true)
                {
                  try
{                  
                         System.out.println(holder.n);
}catch(Exception e)
{
System.out.println("------exception---------" + e); 
}
                    
                }

        }


class Holder 
{
         public int n;

        public Holder(int i)
         {
try
{
// System.out.println("------constructor---------" + n); 
                  Thread.sleep(3);  
}
                catch(Exception e)
         {} 

n=i;
}
}

}

--------------------编程问答-------------------- 这块我也不是太理解,不知道这个例子能否说明问题。希望有更多的人讨论。 --------------------编程问答-------------------- 不是太理解额
补充:Java ,  Web 开发
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,