package 对象及变量的并发访问2;
import 多线程技能1.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* 原子性的测试
* 在32位系统中,针对未使用volatile声明的long或double数据类型没有实现写原子性。
*如果要实现,则声明变量时添加volatile。在64位操作系统中,原子性取决于具体的实现,
*在X86架构64位JDK中,写double和long是原子的。
* 另外,volatile关键最致命的缺点是不支持原子性,也就是多个线程对用volatile修饰的
*变量i执行i++操作时,i++操作还会被分为3步,造成非线程安全问题。
*
* 在32位中,i既不是1也不是-1 而是4294967295
*/
class MyServiceT2320{
public long i;
}
class MyThreadAT2320 extends Thread{
private MyServiceT2320 serviceT2320;
public MyThreadAT2320(MyServiceT2320 serviceT2320){
super();
this.serviceT2320=serviceT2320;
}
@Override
public void run() {
while (true){
serviceT2320.i=1;
}
}
}
class MyThreadBT2320 extends Thread{
private MyServiceT2320 serviceT2320;
public MyThreadBT2320(MyServiceT2320 myServiceT2320){
super();
this.serviceT2320=myServiceT2320;
}
@Override
public void run() {
while (true){
serviceT2320.i=-1;
}
}
}
class TestT2320{
public TestT2320() throws InterruptedException {
MyServiceT2320 myServiceT2320=new MyServiceT2320();
MyThreadAT2320 at2320=new MyThreadAT2320(myServiceT2320);
MyThreadBT2320 bt2320=new MyThreadBT2320(myServiceT2320);
at2320.start();
bt2320.start();
Thread.sleep(1000);
System.out.println("long i 二进制是:"+Long.toBinaryString(1));
System.out.println("long -1 二进制是:"+Long.toBinaryString(-1));
while (true){
long getValue=myServiceT2320.i;
if(getValue!=1&&getValue!=-1){
System.out.println("i的值是:"+Long.toBinaryString(getValue)+"十进制是:"+getValue);
System.exit(0);
}
}
}
}
/**
* 2.使用volatile解决在32位系统中long和double数据类型写操作为非原子性。
*
*/
class MyService2T2320{
volatile public long i ;
}
class MyThreadA2T2320 extends Thread{
private MyService2T2320 service2T2320;
public MyThreadA2T2320(MyService2T2320 service2T2320){
super();
this.service2T2320=service2T2320;
}
@Override
public void run() {
service2T2320.i=1;
}
}
class MyThreadB2T2320 extends Thread{
private MyService2T2320 service2T2320;
public MyThreadB2T2320(MyService2T2320 service2T2320){
super();
this.service2T2320=service2T2320;
}
@Override
public void run() {
service2T2320.i=-1;
}
}
class Test2T2320{
public Test2T2320() throws InterruptedException {
MyService2T2320 myService2T2320=new MyService2T2320();
MyThreadA2T2320 a2T2320=new MyThreadA2T2320(myService2T2320);
MyThreadB2T2320 b2T2320=new MyThreadB2T2320(myService2T2320);
a2T2320.start();
b2T2320.start();
Thread.sleep(1000);
System.out.println("long i 二进制是:"+Long.toBinaryString(1));
System.out.println("long -1 二进制是:"+Long.toBinaryString(-1));
while (true){
long getValue=myService2T2320.i;
if(getValue!=1&&getValue!=-1){
System.out.println("i的值是:"+Long.toBinaryString(getValue)+"十进制是:"+getValue);
System.exit(0);
}
}
}
}
/**
* 3.关键字volatile int i++非原子的特性
* 使用多线程执行volatile int i++赋值操作时为非原子的。
*
* 结果并不是1000;说明count++是非原子的。 更改MyThread类
*
* 如果方法private static void addCount()前加入synchronized同步关键字,那么就没必要
*再使用volatile关键字来声明count变量。
* 关键字volatile使用的主要场合是在多线程中可以感知实例变量被更改了,并且可以获得最新的值,也就是
* 可以用于增加可见性/可视性
* 关键字volatile提示线程每次从共享内存中去读取变量,而不是从私有内存中去读取,这样就保证了同步数
*据的可见性。但如果修改实例数据变量,如i++,并不是一个原子性操作,i++分为以下三步
* 1)从内存中读取i的值
* 2)计算i的值
* 3)将i写入内存
* 如果在第二步时,有多个线程操作,修改i的值,那么这个时候就会出现脏数据,解决办法是使用synchronize
* d关键字。volatile本身并不处理int i++这个操作。
*/
class MyThread3T2320 extends Thread{
volatile public static int count;
private static void addCount(){
for (int i=0;i<100;i++){
count++;
}
System.out.println("count="+count);
}
@Override
public void run() {
addCount();
}
}
class MyThread32T2320 extends Thread{
volatile public static int count;
/**
* 加static关键字——>synchronized与static锁的内容就是MyThread32T2320.class类——>达到同步效果
*/
synchronized private static void addCount(){
for(int i=0;i<100;i++){
count++;
}
System.out.println("count="+count);
}
@Override
public void run() {
addCount();
}
}
class Run3T2320{
public Run3T2320(){
MyThread3T2320 [] myThread3T2320s=new MyThread3T2320[100];
for (int i=0;i<100;i++){
myThread3T2320s[i]=new MyThread3T2320();
}
for(int i=0;i<100;i++){
myThread3T2320s[i].start();
}
}
}
class Run32T2320{
public Run32T2320 (){
MyThread32T2320 [] myThread32T2320s=new MyThread32T2320[100];
for (int i=0;i<100;i++){
myThread32T2320s[i]=new MyThread32T2320();
}
for (int i=0;i<100;i++){
myThread32T2320s[i].start();
}
}
}
/**
* 4.使用Atomic原子进行i++操作实现原子性
* 除了在i++操作时使用synchronized关键字实现同步外,还可以使用AtomicInteger原子实现原子性
* 原子操作是不可分割的整体,没有其他线程能够中断或检查处于原子操作中的变量,一个原子(atomic)
* 类型就是一个原子操作可以类型,它可以没有锁的情况下做到线程安全
*/
class addCountThreadT2320 extends Thread{
private AtomicInteger count=new AtomicInteger(0);
@Override
public void run() {
for (int i=0;i<10000;i++){
System.out.println(count.incrementAndGet());
}
}
}
class Run4T2320{
public Run4T2320(){
addCountThreadT2320 countThreadT2320=new addCountThreadT2320();
Thread thread=new Thread(countThreadT2320);
thread.start();
Thread thread1=new Thread(countThreadT2320);
thread1.start();
Thread thread2=new Thread(countThreadT2320);
thread2.start();
Thread thread3=new Thread(countThreadT2320);
thread3.start();
Thread thread4=new Thread(countThreadT2320);
thread4.start();
}
}
/**
* 5.出现逻辑混乱与解决。
* 在有逻辑的情况下,原子类的输出结果具有随机性。
*/
class MyService5T2320{
public static AtomicLong aiRef=new AtomicLong();
public synchronized void addNum(){
System.out.println(Thread.currentThread().getName()+"100后"+aiRef.addAndGet(100));
aiRef.addAndGet(1);
}
}
class MyThread5T2320 extends Thread{
private MyService5T2320 service5T2320;
public MyThread5T2320(MyService5T2320 service5T2320){
super();
this.service5T2320=service5T2320;
}
@Override
public void run() {
service5T2320.addNum();
}
}
class Run5T2320{
public Run5T2320(){
try {
MyService5T2320 service5T2320=new MyService5T2320();
MyThread5T2320 [] myThread5T2320s=new MyThread5T2320[5];
for (int i=0;i<myThread5T2320s.length;i++){
myThread5T2320s[i]=new MyThread5T2320(service5T2320);
}
for (int i=0;i<myThread5T2320s.length;i++){
myThread5T2320s[i].start();
}
Thread.sleep(1000);
System.out.println(MyService5T2320.aiRef.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class T2320 {
public static void main(String[] args) throws InterruptedException {
//TestT2320 testT2320=new TestT2320();
//Test2T2320 test2T2320=new Test2T2320();
// Run3T2320 run3T2320=new Run3T2320();
//Run32T2320 run32T2320=new Run32T2320();
//Run4T2320 run4T2320=new Run4T2320();
Run5T2320 run5T2320=new Run5T2320();
}
}
02-18
06-27
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交