线程 (综合整理)

线程的基本概念

基本的进程线程概念
进程:是操作系统中进行保护和资源分配的基本单位,操作系统分配资源以进程为基本单位。
线程:是进程的组成部分,它代表了一条顺序的执行流。
线程:另一种解释是从一个main方法进入栈 ,到main方法出栈 栈中没有任何进程 ,这叫一个线程 。
栈帧 :栈中的方法称为栈帧,其都是拷贝过来的,而不是直接拿过来用的。
下面以我的理解,简单说说JVM机制

存放地址信息和与执行顺序相关的信息 ,分为 主栈和子栈
(main方法 是 外边调用的 线程 main方法自己也有一个线程栈)

在堆中的信息 如果是基本类型 则申请固定大小的空间给他
如果是引用类型 则申请他的地址大小的空间,仅仅存放地址 指向它的空间
(栈中存放的信息是与执行顺序相关的 而 堆中 存放的是与顺序无关的信息)

方法区
存放 方法 和 类信息 包括成员和方法 相当于一个蓝图,图纸 实例化相当于按照图纸 制造东西

接下来接着说多线程
多线程是并发执行的
多线程的运行是在一段时间内同时运行 ,他们竞争cpu ,通过时间片的原则运行
两个线程 各自都有一个线程栈 他们如果都调用run 方法
他们都会拷贝一份run方法,以及run方法内部的变量回去,放到栈中
当对 共同的变量进行操作的时候 会产生 线程不安全的问题, 而产生脏数据

public class ThreadDemo extends Thread{	
	private String name;
	private Tree tree;
	ThreadDemo(String name, Tree tree){
		this.name = name;
		this.tree = tree;
	}
    public void run() {
    	ZhanTest bn = new ZhanTest();
    	for(int i = 0; i < 10000; i++) {
    		tree.value += 1;
    	}	
    }
}
public class Test {
//实例化两个线程 让他们都读写tree里边的数据
	public static void main(String[] args) {
		Tree tree = new Tree();
		tree.value = 10;
		int a = 0;
		ThreadDemo t1 = new ThreadDemo("aaa",tree);
		t1.start();
		ThreadDemo t2 = new ThreadDemo("bbb",tree);
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.print(tree.value);
	}

由于读取和写入没有任何限制 所以产生了脏数据。
而这引出了 锁的概念

锁的概念

锁放在方法上 但是实际锁住的是方法中的资源(共享变量的时候加锁)
实际就是线程之间的约定 例如
每次读写不仅读入数据还要读取当前的版本号,然后回去进行操作,当进行写操作的时候,如果自身版本号对不上 则读取新的数据和版本号 ;回去继续操作;
(实际中的锁比这些要版本之类的复杂的多)
(对run加锁是锁不住的,对象的引用类型是锁不住,只能锁住基本类型的数据)

数据:1
锁:A或B // 实现可读入还是等待的控制
版本号:v_1

对象锁:
如果有两个非静态方法 并且都加锁 , 会对所有非静态的加锁
(第一个执行完,第二个才能执行)
伪代码如下:

public  synchronized void a(){
    print("a1");
    Thread.sleep(1000);
     print("a2");
}
public  synchronized void b(){
    print("b1");
    Thread.sleep(1000);
     print("b2");
}
输出:a1a2b1b2

类锁
类锁是锁住整个类,当有多个线程来声明这个类的对象时候将会被阻塞,直到拥有这个类锁的对象呗销毁或者主动释放了类锁,这个时候在被阻塞的线程被挑选出一个占有该类锁,声明该类的对象。其他线程继续被阻塞住

不管多少个对象,共用一把锁,且只有一把,不管怎么调用,都会同步
上面方法加static变类锁:
静态的锁 是类锁,这个类中锁共享, 其在方法区中
如果两个静态的方法都加锁,也会互相锁定。

public static synchronized void a(){
    print("a1");
    Thread.sleep(1000);
     print("a2");
}

public static  synchronized void b(){
    print(" b1");
    Thread.sleep(1000);
     print("b2");
}
输出结果是  a1a2b1b2

加在静态方法的锁属于类锁 ,在方法区,而加在非静态方法的锁是对象锁,在堆中
锁,只在该类中起作用,即内存中的统一资源,在不同的类中不起作用
在编程时候 对锁的资源的读和写要在一个方法中
加在非静态类的方法的锁 锁不住静态的资源
但是,当静态的资源在非静态的加锁的方法中的时,调用该方法的线程需要排队去访问这个静态的资源

public class DataTest {   
   //静态的属于类,非静态的属于对象
   private static int ticket = 100;//静态资源
   
   public synchronized void method1() {
      System.out.println("俺是方法1--1");
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      System.out.println("俺是方法1---2");
   }

   public  synchronized void method2() {
      System.out.println("俺是方法2---1");
      try {
         Thread.sleep(3000);
      } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      System.out.println("俺是方法2---2");
   }
 public  synchronized void method3(String name,FlagTest f) {
    if( ticket == 0) {
       f.flag = 1;
       System.out.println( "卖完了" );
       return;
    }
    System.out.println(name + "卖出了第" + ticket);
    ticket = ticket - 1;
 }
}

public class ThreadTest extends Thread{
    private DataTest data;
    private int flag;
    private String  name;
    
    ThreadTest(DataTest data, int flag, String name){
       this.data = data;
       this.flag = flag;
       this.name = name;
    }
    
    public void run() {
        FlagTest f = new FlagTest();
       while(f.flag == 0) {
          data.method3(name,f);
       }
     
    }
}
public class FlagTest {
    public  int flag = 0;
}
public class Test {
   public static void main(String[] args) {
      DataTest test = new DataTest();
      ThreadTest t1 = new ThreadTest(test,1,"张三");
      ThreadTest t2 = new ThreadTest(test,1,"李四");
      ThreadTest t3 = new ThreadTest(test,1,"王五");
      t1.start();
      t2.start();
      t3.start();
   }
}

在new了每个线程之后 在各自个线程栈中 会压入各自的 run 方法 而他们要操作的资源在一个类中
所以对 那个类中的方法加锁 就可以控制线程对这个资源的读取 从而形成竞争 和 阻塞
在一个对象中 ,如果有个方法有锁,则将这个对象就锁住了。
例如:
如果一个 非静态的加锁的方法 去访问这个对象的 非静态的资源 int aaa;则锁住的这个对象
如果又有一个 非静态的加锁的方法 再去访问这个对象的 非静态的资源 int fff ; 则访问不了进入阻塞
如果是 非静态的不加锁的方法 访问 非静态的资源 int fff 则可以访问;

多线程 并行 并发概念
并行: 线程的资源不竞争 即可并行
并发: 线程之前存在竞争资源 即是并发
Java中的 HashMap 是线程不安全的
加锁与不加锁的区别(不加锁的运行快 ,加锁的运行慢)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值