精华内容
下载资源
问答
  • 大家好,我用CreateProcess创建了一个进程,进程的句柄可以获取到, 请问能否通过此句柄创建一个此进程的子线程? 如果可以,如何实现? 多谢。
  • 一个进程可以创建多少线程

    千次阅读 2018-07-18 23:10:23
    理论上,一个进程可用虚拟空间是2G,默认情况下,线程的栈的大小是1MB,所以理论上最多只能创建2048个线程。如果要创建多于2048的话,必须修改编译器的设置。 #include<windows.h> #include<...

    https://www.cnblogs.com/Leo_wl/p/5969621.html

    理论上,一个进程可用虚拟空间是2G,默认情况下,线程的栈的大小是1MB,所以理论上最多只能创建2048个线程。如果要创建多于2048的话,必须修改编译器的设置。

    #include<windows.h>
    #include<process.h>
    #include<stdio.h>
    HANDLE hProcess;
    HANDLE hThread;
    
    DWORD WINAPI athread(void)    //线程函数
    {
    	WaitForSingleObject(hProcess, INFINITE);
    	return 0;
    }
    bool createThread(int threadNum)    //参数表示创建的线程数
    {
    	int i;
    	hProcess = GetCurrentProcess();
    	for(i = 0; i < threadNum; i++)
    	{
    		hThread = NULL;
    		hThread = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))athread, NULL, NULL, NULL);
    		if(hThread != NULL)
    		{
    			printf("\nThe Number of Thread : %d ", i + 1);
    		}
    		else{
    			printf("\nError : Create Thread Fail.\n");
    			return false;
    		}
    	}
    	return true;
    }
    int main()
    {
    	printf("Test : How much thread a process can create.\n");
    	createThread(4500);
    	getchar();
    	return 0;
    }

    结论:

    一个进程可以创建的线程数由可用虚拟空间和线程的栈的大小共同决定,只要虚拟空间足够,那么新线程的建立就会成功。如果需要创建超过2K以上的线程,减小你线程栈的大小就可以实现了。

    展开全文
  • 被问懵了:一个进程最多可以创建多少个线程

    千次阅读 多人点赞 2021-07-15 09:19:09
    大致意思就是,他看了一个面经,说虚拟内存是 2G 大小,然后他看了我的图解系统 PDF 里说虚拟内存是 4G,然后他就懵逼了。 其实他看这个面经很有问题,没有说明是什么操作系统,以及是多少位操作系统。 因为不同的...

    大家好,我是小林。

    昨天有位读者问了我这么个问题:


    大致意思就是,他看了一个面经,说虚拟内存是 2G 大小,然后他看了我的图解系统 PDF 里说虚拟内存是 4G,然后他就懵逼了。

    其实他看这个面经很有问题,没有说明是什么操作系统,以及是多少位操作系统。

    因为不同的操作系统和不同位数的操作系统,虚拟内存可能是不一样多。

    Windows 系统我不了解,我就说说 Linux 系统。

    在 Linux 操作系统中,虚拟地址空间的内部又被分为内核空间和用户空间两部分,不同位数的系统,地址 空间的范围也不同。比如最常⻅的 32 位和 64 位系统,如下所示:

    通过这里可以看出:

    • 32 位系统的内核空间占用 1G ,位于最高处,剩下的 3G 是用户空间;
    • 64 位系统的内核空间和用户空间都是 128T ,分别占据整个内存空间的最高和最低处,剩下的中
      间部分是未定义的。

    接着,来看看读者那个面经题目:一个进程最多可以创建多少个线程?

    这个问题跟两个东西有关系:

    • 进程的虚拟内存空间上限,因为创建一个线程,操作系统需要为其分配一个栈空间,如果线程数量越多,所需的栈空间就要越大,那么虚拟内存就会占用的越多。
    • 系统参数限制,虽然 Linux 并没有内核参数来控制单个进程创建的最大线程个数,但是有系统级别的参数来控制整个系统的最大线程个数。

    我们先看看,在进程里创建一个线程需要消耗多少虚拟内存大小?

    我们可以执行 ulimit -a 这条命令,查看进程创建线程时默认分配的栈空间大小,比如我这台服务器默认分配给线程的栈空间大小为 8M。

    在前面我们知道,在 32 位 Linux 系统里,一个进程的虚拟空间是 4G,内核分走了1G,留给用户用的只有 3G

    那么假设创建一个线程需要占用 10M 虚拟内存,总共有 3G 虚拟内存可以使用。于是我们可以算出,最多可以创建差不多 300 个(3G/10M)左右的线程。

    如果你想自己做个实验,你可以找台 32 位的 Linux 系统运行下面这个代码:

    由于我手上没有 32 位的系统,我这里贴一个网上别人做的测试结果:

    如果想使得进程创建上千个线程,那么我们可以调整创建线程时分配的栈空间大小,比如调整为 512k:

    $ ulimit -s 512
    

    说完 32 位系统的情况,我们来看看 64 位系统里,一个进程能创建多少线程呢?

    我的测试服务器的配置:

    • 64 位系统;
    • 2G 物理内存;
    • 单核 CPU。

    64 位系统意味着用户空间的虚拟内存最大值是 128T,这个数值是很大的,如果按创建一个线程需占用 10M 栈空间的情况来算,那么理论上可以创建 128T/10M 个线程,也就是 1000多万个线程,有点魔幻!

    所以按 64 位系统的虚拟内存大小,理论上可以创建无数个线程。

    事实上,肯定创建不了那么多线程,除了虚拟内存的限制,还有系统的限制。

    比如下面这三个内核参数的大小,都会影响创建线程的上限:

    • /proc/sys/kernel/threads-max,表示系统支持的最大线程数,默认值是 14553
    • /proc/sys/kernel/pid_max,表示系统全局的 PID 号数值的限制,每一个进程或线程都有 ID,ID 的值超过这个数,进程或线程就会创建失败,默认值是 32768
    • /proc/sys/vm/max_map_count,表示限制一个进程可以拥有的VMA(虚拟内存区域)的数量,具体什么意思我也没搞清楚,反正如果它的值很小,也会导致创建线程失败,默认值是 65530

    那接下针对我的测试服务器的配置,看下一个进程最多能创建多少个线程呢?

    我在这台服务器跑了前面的程序,其结果如下:

    可以看到,创建了 14374 个线程后,就无法在创建了,而且报错是因为资源的限制。

    前面我提到的 threads-max 内核参数,它是限制系统里最大线程数,默认值是 14553。

    我们可以运行那个测试线程数的程序后,看下当前系统的线程数是多少,可以通过 top -H 查看。

    左上角的 Threads 的数量显示是 14553,与 threads-max 内核参数的值相同,所以我们可以认为是因为这个参数导致无法继续创建线程。

    那么,我们可以把 threads-max 参数设置成 99999:

    echo 99999 > /proc/sys/kernel/threads-max
    

    设置完 threads-max 参数后,我们重新跑测试线程数的程序,运行后结果如下图:

    可以看到,当进程创建了 32326 个线程后,就无法继续创建里,且报错是无法继续申请内存。

    此时的上限个数很接近 pid_max 内核参数的默认值(32768),那么我们可以尝试将这个参数设置为 99999:

    echo 99999 > /proc/sys/kernel/pid_max
    

    设置完 pid_max 参数后,继续跑测试线程数的程序,运行后结果创建线程的个数还是一样卡在了 32768 了。

    当时我也挺疑惑的,明明 pid_max 已经调整大后,为什么线程个数还是上不去呢?

    后面经过查阅资料发现,max_map_count 这个内核参数也是需要调大的,但是它的数值与最大线程数之间有什么关系,我也不太明白,只是知道它的值是会限制创建线程个数的上限。

    然后,我把 max_map_count 内核参数也设置成后 99999:

    echo 99999 > /proc/sys/kernel/max_map_count 
    

    继续跑测试线程数的程序,结果如下图:

    当创建差不多 5 万个线程后,我的服务器就卡住不动了,CPU 都已经被占满了,毕竟这个是单核 CPU,所以现在是 CPU 的瓶颈了。

    我只有这台服务器,如果你们有性能更强的服务器来测试的话,有兴趣的小伙伴可以去测试下。

    接下来,我们换个思路测试下,把创建线程时分配的栈空间调大,比如调大为 100M,在大就会创建线程失败。

    ulimit -s 1024000
    

    设置完后,跑测试线程的程序,其结果如下:

    总共创建了 26390 个线程,然后就无法继续创建了,而且该进程的虚拟内存空间已经高达 25T,要知道这台服务器的物理内存才 2G。

    为什么物理内存只有 2G,进程的虚拟内存却可以使用 25T 呢?

    因为虚拟内存并不是全部都映射到物理内存的,程序是有局部性的特性,也就是某一个时间只会执行部分代码,所以只需要映射这部分程序就好。

    你可以从上面那个 top 的截图看到,虽然进程虚拟空间很大,但是物理内存(RES)只有使用了 400 多M。

    好了,简单总结下:

    • 32 位系统,用户态的虚拟空间只有 3G,如果创建线程时分配的栈空间是 10M,那么一个进程最多只能创建 300 个左右的线程。
    • 64 位系统,用户态的虚拟空间大到有 128T,理论上不会受虚拟内存大小的限制,而会受系统的参数或性能限制。

    絮叨絮叨

    小林在 CSDN 写了很多图解网络和操作系统的系列文章,很高兴收获到很朋友的认可和支持,正好最近图解网络和操作系统的文章连载的有 20+ 篇了,也算有个体系了。

    在这里插入图片描述

    所以为了方便大家阅读,小林把自己原创的图解网络和图解操作系统整理成了 PDF,一整理后,没想到每个图解都输出了 15 万字 + 500 张图,质量也是杠杠的,有很多朋友特地私信我,看了我的图解拿到了大厂的offer。

    图解系统 PDF 开源下载:图解系统 PDF 下载地址(点击)

    图解网络 PDF 开源下载:图解网络 PDF 下载地址(点击)


    我是小林,今天的你,比昨天更博学了吗?

    展开全文
  • 进程线程

    万次阅读 多人点赞 2021-03-17 22:50:20
    进程与线程 1 进程 1.1 进程的概念 进程就是正在运行的程序,它代表了程序所占用的内存区域 1.2 进程的特点 独立性 进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的...多个进程可以

    进程与线程

    1 进程

    1.1 进程的概念

    进程就是正在运行的程序,它会占用对应的内存区域,由CPU进行执行与计算。

    1.2 进程的特点

    • 独立性
      进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间
    • 动态性
      进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合,程序加入了时间的概念以后,称为进程,具有自己的生命周期和各种不同的状态,这些概念都是程序所不具备的.
    • 并发性
      多个进程可以在单个处理器CPU上并发执行,多个进程之间不会互相影响.

    2 线程

    2.1 线程的概念

    线程是操作系统OS能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.
    一个进程可以开启多个线程,其中有一个主线程来调用本进程中的其他线程。
    我们看到的进程的切换,切换的也是不同进程的主线程
    多线程可以让同一个进程同时并发处理多个任务,相当于扩展了进程的功能。

    2.2 进程与线程的关系

    一个操作系统中可以有多个进程,一个进程中可以包含一个线程(单线程程序),也可以包含多个线程(多线程程序)
    进程与线程的关系
    每个线程在共享同一个进程中的内存的同时,又有自己独立的内存空间.
    所以想使用线程技术,得先有进程,进程的创建是OS操作系统来创建的,一般都是C或者C++完成
    进程与线程的关系

    3 多线程的特性

    3.1 随机性

    我们宏观上觉得多个进程是同时运行的,但实际的微观层面上,一个CPU【单核】只能执行一个进程中的一个线程。
    那为什么看起来像是多个进程同时执行呢?
    是因为CPU以纳秒级别甚至是更快的速度高效切换着,超过了人的反应速度,这使得各个进程从看起来是同时进行的,也就是说,宏观层面上,所有的进程看似并行【同时运行】,但是微观层面上是串行的【同一时刻,一个CPU只能处理一件事】。
    线程切换

    串行与并行

    串行是指同一时刻一个CPU只能处理一件事,类似于单车道
    并行是指同一时刻多个CPU可以处理多件事,类似于多车道
    在这里插入图片描述
    在这里插入图片描述

    3.2 CPU分时调度

    时间片,即CPU分配给各个线程的一个时间段,称作它的时间片,即该线程被允许运行的时间,如果在时间片用完时线程还在执行,那CPU将被剥夺并分配给另一个线程,将当前线程挂起,如果线程在时间片用完之前阻塞或结束,则CPU当即进行切换,从而避免CPU资源浪费,当再次切换到之前挂起的线程,恢复现场,继续执行。
    注意:我们无法控制OS选择执行哪些线程,OS底层有自己规则,如:

    1. FCFS(First Come First Service 先来先服务算法)
    2. SJS(Short Job Service短服务算法)

    CPU分片

    3.3 线程的状态

    由于线程状态比较复杂,我们由易到难,先学习线程的三种基础状态及其转换,简称”三态模型” :

    • 就绪(可运行)状态:线程已经准备好运行,只要获得CPU,就可立即执行
    • 执行(运行)状态:线程已经获得CPU,其程序正在运行的状态
    • 阻塞状态:正在运行的线程由于某些事件(I/O请求等)暂时无法执行的状态,即线程执行阻塞
      线程的3种状态

    就绪 → 执行:为就绪线程分配CPU即可变为执行状态"
    执行 → 就绪:正在执行的线程由于时间片用完被剥夺CPU暂停执行,就变为就绪状态
    执行 → 阻塞:由于发生某事件,使正在执行的线程受阻,无法执行,则由执行变为阻塞
    (例如线程正在访问临界资源,而资源正在被其他线程访问)
    反之,如果获得了之前需要的资源,则由阻塞变为就绪状态,等待分配CPU再次执行

    我们可以再添加两种状态:

    • 创建状态:线程的创建比较复杂,需要先申请PCB,然后为该线程运行分配必须的资源,并将该线程转为就绪状态插入到就绪队列中
    • 终止状态:等待OS进行善后处理,最后将PCB清零,并将PCB返回给系统
      线程的5种状态

    PCB(Process Control Block):为了保证参与并发执行的每个线程都能独立运行,OS配置了特有的数据结构PCB来描述线程的基本情况和活动过程,进而控制和管理线程

    3.4 线程状态与代码对照

    线程状态与代码对照
    线程生命周期,主要有五种状态:

    1. 新建状态(New) : 当线程对象创建后就进入了新建状态.如:Thread t = new MyThread();
    2. 就绪状态(Runnable):当调用线程对象的start()方法,线程即为进入就绪状态.
      处于就绪(可运行)状态的线程,只是说明线程已经做好准备,随时等待CPU调度执行,并不是执行了t.start()此线程立即就会执行
    3. 运行状态(Running):当CPU调度了处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态
      就绪状态是进入运行状态的唯一入口,也就是线程想要进入运行状态状态执行,先得处于就绪状态
    4. 阻塞状态(Blocked):处于运状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行.
      根据阻塞状态产生的原因不同,阻塞状态又可以细分成三种:
      等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态
      同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态
      其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态.当sleep()状态超时.join()等待线程终止或者超时或者I/O处理完毕时线程重新转入就绪状态
    5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

    4 多线程代码创建方式1:继承Thread

    4.1 概述

    Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例
    启动线程的唯一方法就是通过Thread类的start()实例方法
    start()方法是一native方法,它将通知底层操作系统,.最终由操作系统启动一个新线程,操作系统将执行run()
    这种方式实现的多线程很简单,通过自己的类直接extends Thread,并重写run()方法,就可以自动启动新线程并执行自己定义的run()方法
    模拟开启多个线程,每个线程调用run()方法.

    4.2 常用方法

    构造方法

    Thread() 分配新的Thread对象
    Thread(String name) 分配新的Thread对象
    Thread(Runnable target) 分配新的Thread对象
    Thread(Runnable target,String name) 分配新的Thread对象

    普通方法

    static Thread currentThread( )
    返回对当前正在执行的线程对象的引用
    long getId()
    返回该线程的标识
    String getName()
    返回该线程的名称
    void run()
    如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法
    static void sleep(long millions)
    在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
    void start()
    使该线程开始执行:Java虚拟机调用该线程的run()

    4.3 测试多线程的创建方式1

    创建包: cn.tedu.thread
    创建类: TestThread1.java

    package cn.tedu.thread;
    /*本类用于多线程编程实现方案一:继承Thread类来完成*/
    public class TestThread1 {
        public static void main(String[] args) {
            //4.创建线程对象进行测试
            /*4.new对应的是线程的新建状态
            * 5.要想模拟多线程,至少得启动2个线程,如果只启动1个,是单线程程序*/
            MyThread t1 = new MyThread();
            MyThread t2 = new MyThread();
            MyThread t3 = new MyThread();
            MyThread t4 = new MyThread();
            /*6.这个run()如果直接这样调用,是没有多线程抢占执行的效果的
            * 只是把这两句话看作普通方法的调用,谁先写,就先执行谁*/
            //t1.run();
            //t2.run();
            /*7.start()对应的状态就是就绪状态,会把刚刚新建好的线程加入到就绪队列之中
            * 至于什么时候执行,就是多线程执行的效果,需要等待OS选中分配CPU
            * 8.执行的时候start()底层会自动调用我们重写的run()种的业务
            * 9.线程的执行具有随机性,也就是说t1-t4具体怎么执行
            * 取决于CPU的调度时间片的分配,我们是决定不了的*/
            t1.start();//以多线程的方式启动线程1,将当前线程变为就绪状态
            t2.start();//以多线程的方式启动线程2,将当前线程变为就绪状态
            t3.start();//以多线程的方式启动线程3,将当前线程变为就绪状态
            t4.start();//以多线程的方式启动线程4,将当前线程变为就绪状态
        }
    }
    
    //1.自定义一个多线程类,然后让这个类继承Thread
    class MyThread extends Thread{
        /*1.多线程编程实现的方案1:通过继承Thread类并重写run()来完成的 */
        //2.重写run(),run()里是我们自己的业务
        @Override
        public void run() {
            /*2.super.run()表示的是调用父类的业务,我们现在要用自己的业务,所以注释掉*/
            //super.run();
            //3.完成业务:打印10次当前正在执行的线程的名称
            for (int i = 0; i < 10; i++) {
                /*3.getName()表示可以获取当前正在执行的线程名称
                * 由于本类继承了Thread类,所以可以直接使用这个方法*/
                System.out.println(i+"="+getName());
            }
        }
    }
    

    5 多线程代码创建方式2:实现Runnable接口

    5.1 概述

    如果自己的类已经extends另一个类,就无法多继承,此时,可以实现一个Runnable接口

    5.2 常用方法

    void run()使用实现接口Runnable的对象创建线程时,启动该线程将导致在独立执行的线程中调用对象的run()方法

    5.3 练习2:测试多线程的创建方式2

    创建包: cn.tedu.thread
    创建类: Thread2.java

    package cn.tedu.thread;
    /*本类用于多线程编程实现方案二:实现Runnable接口来完成*/
    public class TestThread2 {
        public static void main(String[] args) {
            //5.创建自定义类的对象--目标业务类对象
            MyRunnable target = new MyRunnable();
            //6.如何启动线程?自己没有,需要与Thread建立关系
            Thread t1 = new Thread(target);
            Thread t2 = new Thread(target);
            Thread t3 = new Thread(target);
            Thread t4 = new Thread(target);
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    
    //1.自定义多线程类
    class MyRunnable implements Runnable{
        //2.添加父接口中的抽象方法run(),里面是自己的业务
        @Override
        public void run() {
            //3.写业务,打印10次当前正在执行的线程名称
            for (int i = 0; i < 10; i++) {
                /*问题:自定义类与父接口Runnable中都没有获取名字的方法
                * 所以还需要从Thread中找:
                * currentThread():静态方法,获取当前正在执行的线程对象
                * getName():获取当前线程的名称*/
                System.out.println(i+"="+Thread.currentThread().getName());
            }
        }
    }
    

    5.4 两种实现方式的比较

    • 继承Thread类
      优点: 编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this即可获得当前线程
      缺点: 自定义的线程类已继承了Thread类,所以后续无法再继承其他的类
    • 实现Runnable接口
      优点: 自定义的线程类只是实现了Runnable接口或Callable接口,后续还可以继承其他类,在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码、还有数据分开(解耦),形成清晰的模型,较好地体现了面向对象的思想
      缺点: 编程稍微复杂,如想访问当前线程,则需使用Thread.currentThread()方法

    6 售票案例

    需求:设计4个售票窗口,总计售票100张。用多线程的程序设计并写出代码

    6.1 方案1:继承Thread

    创建包: cn.tedu.tickets
    创建类: TestThread.java

    package cn.tedu.tickets;
    /*需求:设计多线程编程模型,4个窗口共计售票100张
    * 本方案使用多线程编程方案1,继承Thread类的方式来完成*/
    public class TestThread {
        public static void main(String[] args) {
            //5.创建多个线程对象
            TicketThread t1 = new TicketThread();
            TicketThread t2 = new TicketThread();
            TicketThread t3 = new TicketThread();
            TicketThread t4 = new TicketThread();
            //6.以多线程的方式启动
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    
    //1.自定义多线程售票类,继承Thread
    class TicketThread extends Thread{
        //3.定义变量,保存要售卖的票数
        /*问题:4个线程对象共计售票400张,原因是创建了4次对象,各自操作各自的成员变量
        * 解决:让所有对象共享同一个数据,票数需要设置为静态*/
        static int tickets = 100;
        //2.重写父类的run(),里面是我们的业务
        @Override
        public void run() {
            //4.1循环卖票
            while(true){
                try {
                    //7.让每个线程经历休眠,增加线程状态切换的频率与出错的概率
                    //问题1:产生了重卖的现象:同一张票卖了多个人
                    //问题2:产生了超卖的现象:超出了规定的票数100,出现了0 -1 -2这样的票
                    Thread.sleep(10);//让当前线程休眠10ms
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //4.2打印当前正在卖票的线程名称,并且票数-1
                System.out.println(getName()+"="+tickets--);
                //4.3做判断,如果没有票了,就退出死循环
                if(tickets <= 0) break;//注意,死循环一定要设置出口
            }
        }
    }
    

    6.2 方案2:实现Runnable

    创建包: cn.tedu.tickets
    创建类: TestRunnable.java

    package cn.tedu.tickets;
    /*需求:设计多线程编程模型,4个窗口共计售票100张
     * 本方案使用多线程编程方案2,实现Runnable接口的方式来完成*/
    public class TestRunnable {
        public static void main(String[] args) {
            //5.创建Runnable接口的实现类对象,作为目标业务对象
            TicketRunnable target = new TicketRunnable();
            //6.创建多个Thread类线程对象,并将target业务对象交给多个线程对象来处理
            Thread t1 = new Thread(target);
            Thread t2 = new Thread(target);
            Thread t3 = new Thread(target);
            Thread t4 = new Thread(target);
            //7.以多线程的方式启动多个线程对象
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    
    //1.自定义多线程类实现Runnable接口
    class TicketRunnable implements Runnable{
        //3.定义一个成员变量,用来保存票数100
        /*由于自定义类对象只创建了一次,所以票数被所有线程对象Thread类的对象共享*/
        int tickets = 100;
        //2.添加接口中未实现的方法,方法里是我们的业务
        @Override
        public void run() {
            //4.1循环卖票
            while(true){
                //8.让线程休眠10ms,增加线程状态切换的概率和出错的概率
                try {
                    Thread.sleep(10);//让当前线程休眠10ms
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //4.2打印当前正在售票的线程名称 & 票数-1
                System.out.println(Thread.currentThread().getName()+"="+tickets--);
                //4.3设置死循环的出口,没票了就停止卖票
                if(tickets <=0 ) break;
            }
        }
    }
    

    6.3 问题

    1. 每次创建线程对象,都会生成一个tickets变量值是100,创建4次对象就生成了400张票了。不符合需求,怎么解决呢?能不能把tickets变量在每个对象间共享,就保证多少个对象都是卖这100张票。
      解决方案: 用静态修饰
    2. 产生超卖,0 张 、-1张、-2张。
    3. 产生重卖,同一张票卖给多人。
    4. 多线程安全问题是如何出现的?常见情况是由于线程的随机性+访问延迟。
    5. 以后如何判断程序有没有线程安全问题?
      在多线程程序中 + 有共享数据 + 多条语句操作共享数据
      解决方案:下一节 同步锁点这里
    展开全文
  • 每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。 第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序...

    进程-线程-多线程

    1、进程(process)
    狭义定义:进程就是一段程序的执行过程
    简单的来讲进程的概念主要有两点:
    第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。
    第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
    进程状态:进程有三个状态,就绪、运行、阻塞。

    511遇见易语言多线程大漠多线程


    2、线程(thread)
    通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源。
    3、进程与线程的区别:
    每个进程都有私有的虚拟地址空间,进程的所有线程共享同一地址空间。每个线程被CPU分配一个时间片,一旦被激活,它正常运行直到时间片耗尽并被挂起,此时,操作系统选择另一个线程进行运行。
    简而言之,一个进程至少有一个线程.
    线程的划分尺度小于进程,使得多线程程序的并发性高。
    1)线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
    2)一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
    3)进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
    4)调度和切换:线程上下文切换比进程上下文切换要快得多。
    4、什么是单线程和多线程?
    单线程,顾名思义即是只有一条线程在执行任务
    多线程,创建多条线程同时执行任务
    5、并行和并发的区别,
    并发:交替做不同事的能力
    并行:同时做不同事的能力
    行话解释:
    并发:不同代码块交替执行的性能
    并行:不同代码块同时执行的性能
    6、多线程在多核上是并发还是并行?
    对于单核,多线程的多任务是在单cpu交替执行,属于并发;
    对于多核,多线程的任务如果能够分布在各个cpu,上(线程数少许核心数),那么就是并行。
    7、拓展
    同步和异步 ----- 异步的反义词是同步
    顺序和并发 ----- 并发的反义词是顺序
    串行和并行 ----- 并行的反义词是串行
    简单的说:并行是多线程的一种形式,多线程是并发的一种形式。异步也是并发的一种形式。
    8、线程的生命周期
    9、线程的安全
    10、线程池

    展开全文
  • 进程(process)和线程(thread)是操作系统的基本概念 进程是具有一定独立功能的程序关于某个数据集合上的一次运行...一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行进程和线程的区别在
  • 多线程():创建线程线程的常用方法

    万次阅读 多人点赞 2018-09-01 19:14:23
    了解并发编程:实际工作中很少写多线程的代码,这部分代码一般都被人封装起来了,在业务中使用多线程的机会也不是很(看具体项目),但是作为一个高级程序员如果不会多线程是说不过去的。 二:进程线程 ...
  • 进程线程的区别(超详细)

    万次阅读 多人点赞 2019-10-03 21:57:46
    进程和线程 进程 一个在内存中运行的应用...一个进程至少有一个线程,一个进程可以运行多个线程多个线程可共享数据。 与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟...
  • python多进程线程,多个程序同时运行

    千次阅读 多人点赞 2021-04-08 13:47:15
    python 多线程进程同时运行 多任务要求 python 基础语法 python 文件目录操作 python 模块应用 开发工具 pycharm ...在段时间内交替执行多个任务, 例如单核cpu 处理多任务, 操作系统让各个任务交
  • 多进程多线程区别

    万次阅读 多人点赞 2016-04-21 10:01:16
    Apache是采用进程的(perfork模式,每客户连接对应一个进程,每进程中只存在唯一一个执行线程), Java的Web容器Tomcat、Websphere等都是多线程的(每客户连接对应一个线程,所有线程都在一个进程中)。...
  • 一个进程最多创建多少个线程

    千次阅读 2018-10-10 23:02:38
    最近,在做一个关于聊天服务器的项目,其中遇到了一个问题,那就是一个进程可以产生多少个线程呢? 开始各种想象,会和不同平台,不同系统相关,网上很大佬说是1024个,也有256个。 与其无端猜测,不如动手测试...
  • 一个进程最多可以创建线程的数目

    千次阅读 2017-10-02 22:13:47
    如果使用VS,链接程序开关/SACK 或者/F可以设置线程堆栈大小,默认分配一个线程的堆栈大小是1MB,当CreateThread参数的StackSize大小与链接程序设置的不一致时,采用的方法是谁大用谁的,所以用4K
  • 线程进程多线程多进程任务 小结

    千次阅读 多人点赞 2019-04-20 11:59:56
    3 多进程 4 多线程 5 线程进程的关系 6 线程进程的区别 7 进程的优缺点 7.1 进程的优点 7.2 进程的缺点 8 线程的优缺点 8.1 线程的优点 8.2 线程的缺点 9 多线程的优缺点 9.1 多线程的优点 9.2 ...
  •  一个进程包括由操作系统分配的内存空间,包含一个多个线程一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。 线程  又称其为轻量级进程...
  • 线程VS进程

    万次阅读 2021-03-10 16:44:19
    比如说QQ是是一个进程,如果你在和A朋友语音聊天的同时和B朋友打字聊天,同时还在QQ群下载图片,这三个操作就相当于开启了三个线程可以说有了线程之后我们设计的程序就可以一边执行A操作,一边执行B操作了。...
  • 线程:程序执行的最小单元,是进程中的一个实体用来执行程序,一个进程中有多个线程。 既然如此,我们可以想象,一个系统中的进程数量肯定是有上限的,不然系统资源就会不够用了,同样的道理,一个进程中的线程...
  • 个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也...
  • 进程与线程的关系 简单复习一下:一个”进程“代表中计算机中实际跑起来的一个程序,在现代操作系统...因此一个进程至少得有一个线程,我们把这个线程称之为”主线程“,也就是说,一个进程至少要有一个主线程。 ...
  • 背景:同学公司的传感器设备需要将收集的数据发到服务器上,前期想写一个简单的服务器来测试下使用效果,设备收集的数据非常的重要,所以考虑使用TCP协议来实现。 因为只是测试使用,所以采用多线程的方式,毕竟...
  • 线程是程序执行的最小单元,是进程中的一个实体用来执行程序,一个进程中有多个线程一个系统中的进程数量肯定是有上限的,不然系统资源就会不够用了,同样的道理,一个进程中的线程资源也是有上限的。那进程和...
  • 2.1 线程创建 2.2 守护线程 2.3守护线程和非守护线程并存的情况 2.4锁的基本用法 三:多进程和守护进程 3.1 多进程创建 3.2守护进程创建 四:选择线程还是多进程 近期在工作中,遇到了Python的线程和...
  • python 彻底解读多线程多进程

    万次阅读 多人点赞 2019-03-26 14:20:34
    title: 多线程多进程 copyright: true top: 0 date: 2019-03-03 16:16:41 tags: 多线程多进程 categories: Python高阶笔记 permalink: password: keywords: description: 对python的多线程多进程进一步刨析。 真是...
  • 多线程多进程

    千次阅读 2019-02-27 10:26:49
    多线程共享进程数据:共享简单;同步复杂 各有优势 内存、CPU 占用内存,切换复杂,CPU利用率低 占用内存少,切换简单,CPU利用率高 线程占优 创建销毁、切换 创建销毁、切换复杂,速度慢 创建...
  • 一个进程可以创建多少线程

    千次阅读 2009-04-16 17:09:00
    以前一直没有试过也没怎么想过这问题,模糊觉得和系统性能与有关系,前2天写小程序试了一下,如下#include "stdafx.h"#include "stdio.h"#include "stdlib.h"#include "windows.h"#include "process.h"unsigned ...
  • 一个进程所拥有的数据和变量只属于它自己。 线程(thread):是进程内相对独立的可执行单元,所以也被称为轻量进程(lightweight processes);是操作系统进行任务调度的基本单元。它与父进程的其它线程共享该进程所...
  • Python——多线程多进程

    千次阅读 2021-07-13 12:53:27
    当有多个线程,并且在这个几个线程中都会去调用deposit,就有可能同时操作这个bank对象,就有可能出一个线程覆盖另外一个线程的结果的问题。这时,可以使用 threading库里面的锁对象 Lock 去保护。 from threading ...
  • 多线程多进程、线程池、进程

    千次阅读 2017-04-11 15:01:18
    多任务不管是单核CPU还是多核CPU,一旦任务数量超过核数,OS都会把每个任务轮流调度到每个核心上。...一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。 还有一种方法是启动
  • 多进程多线程编程操作

    千次阅读 2018-08-18 17:17:22
    1.什么是进程 进程是系统最小的资源管理单元,是一个程序在一个数据集上的一次动态执行过程。...一个进程可以多个线程,而一个线程只服务于一个进程。 3.程序执行方法 串行 按照一定的步骤执行每个环节 ...
  • 搞定python多线程多进程

    千次阅读 2017-07-10 13:14:11
    一条线程指的是进程中一个单一顺序的控制流,一个进程可以并发多个线程,每条线程并行执行不同的任务。一个线程一个execution context(执行上下文),即一个cpu执行时所需要的一串指令。1.1.2 线程的工作方式...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 543,568
精华内容 217,427
关键字:

一个线程可以创建多个进程吗