dll文件在同一个程序的多线程情况下,是共享的吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dll文件在同一个程序的多线程情况下,是共享的吗?相关的知识,希望对你有一定的参考价值。

参考技术A

共享一份DLL。

原因涉及DLL加载和运行机制,主要有两点:

1)DLL动态链接库无法独立运行,必须由一个应用程序进程加载到进程空间后才能使用。加载DLL的进程称为宿主进程。被加载的DLL属于宿主进程,不属于宿主进程内某个线程。

2)宿主进程可以重复调用,甚至重复加载DLL。第1次调用DLL或第1次加载DLL时,宿主进程将DLL引入进程空间。一旦宿主进程成功加载DLL,随后的重复调用或重复加载只会增加“引用计数”,而不会加载多份DLL,所以进程中只有一份DLL。

总结下自己理解的多线程知识

1.多线程概念
进程:一个正在运行的程序就可以看作是一个进程。每个进程都有自己独立
的内存空间。
线程:一个程序的执行顺序控制流就可以看作是一个线程。
进程和线程的区别:
1.每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较
大的开销。
2.线程可以看成时轻量级的进程,同一类线程共享代码和数据空间,每个
线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
多进程:在操作系统中能同时运行多个程序(任务)
多线程:在同一应用程序中有多个顺序流同时执行,在一个进程里可以有1条
或多条线程,但是至少要有一条线程。多线程能够提高程序的执行效率。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
2.main线程(主线程)
在程序里有一个public static void main(String[] args)方法,这个方法是程序
的入口,这是一个固定的写法。
当程序启动时,JVM虚拟机会自动的创建main线程(主线程),在主线程里
会自动的调用main()方法,就会执行main()方法里的代码。我们编写的代码都
是写在main()方法中,所以我们写的代码都是在主线程(main线程)执行的。
3.创建子线程的(两种方式)
Thread类:描述线程里的属性(线程的名称,线程的优先级,线程执行的任
务),基于面向对象的思想就把线程的属性封装成Thread类。
Thread类的方法:
a.普通方法
getName():获取线程对象的名称。
start():启动线程。
b.静态方法:类名.方法名
currentThread():获取当前正在执行的线程对象。
Thread curThead = Thread.currentThread();
System.out.println(curThead.getName());
3.1创建子线程方式一:
a.声明一个类继承Thread类,并重写run()方法。

技术分享图片
3.2创建子线程方式二:
a.实现Runnable接口,重写run()方法。

技术分享图片
b.通过匿名内部类开启子线程
技术分享图片
4.Thread类常用方法
静态方法:类名.方法名()
currentThread():返回一个正在执行的线程对象。
sleep():让当前线程睡醒指定毫秒数。
普通方法:
getName():获取线程对象的名称
start():开启子线程
(1)sleep():让当前线程睡醒指定毫秒数,不会释放锁。是Thread类的静态方法,可以在任意位置使用。
//睡眠1秒
Thread.sleep(1000);
(2)isAlive():判断线程是否还“活”着,即线程是否还未终止。
线程的优先级:
线程的优先级越高表示这个线程执行的概率越高。
线程优先级值的范围:1~10,最低1,最高10.
(3)getPriority():获取线程的优先级。
(4)setPriority():设置线程的优先级。
(5)join():调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
(6)yield():让出CPU,当前线程进入就绪队列等待调度。
(7)wait():让线程进入等待池wait pool进入阻塞状态并释放锁,直到notify()或者notifyAll()唤醒。是object类的对象方法,只能在互斥锁(同步锁)里使用。
(8)notify()或者notifyAll()唤醒等待池wait pool里的线程。
5.互斥锁(同步锁)(重点)
解决多线程安全问题就是用同步锁。
a.给代码加锁
public void run()
{
Thread.sleep(500);
//在run()方法里的访问变量加锁
//类名.class是钥匙
synchronized(类名.class)
{//开始加锁
xinXi1.num++;
System.out.println(Thread.currentThread().getName() + xinXi1.num);
}//释放锁
}
例子:
public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("线程1");
subThread subThread = new subThread("线程2");
addThread.start();
subThread.start();
}
}
//加法子线程继承Thread
class addThread extends Thread{
public addThread(String name){

    super(name);
}
@Override
public void run()
{
    try
    {
        addThread.sleep(3000);
    } catch (InterruptedException e)
    {
        e.printStackTrace();
    }

//给代码加锁
synchronized (xinXi1.class)
{
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法后="+xinXi1.num);
}
}
}
//减法子线程继承Thread
class subThread extends Thread{
public subThread(String name){

    super(name);
}
@Override
public void run()
{
    try
    {
        subThread.sleep(3000);
    } catch (InterruptedException e)
    {
        e.printStackTrace();
    }
    synchronized (xinXi1.class)
    {
        xinXi1.num--;
        System.out.println(subThread.currentThread().getName()+"减法后="+xinXi1.num);
    }       
}

}
b.给方法加锁
例子:

public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("线程1");
subThread subThread = new subThread("线程2");
addThread.start();
subThread.start();
}
//给方法加锁
public static synchronized void add(){
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法后="+xinXi1.num);
}
//给方法加锁
public static synchronized void sub(){
xinXi1.num--;
System.out.println(subThread.currentThread().getName()+"减法后="+xinXi1.num);
}

}
class addThread extends Thread{
public addThread(String name){br/>super(name);
}
@Override
public void run()
{
try
{
addThread.sleep(3000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//线程里调用方法
xinXi1.add();
}
}
class subThread extends Thread{
public subThread(String name){
br/>super(name);
}
@Override
public void run()
{
try
{
subThread.sleep(3000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//线程里调用方法
xinXi1.sub();
}
}
注意事项:
1.synchronized(){}大括号里的代码就是加锁的代码,注意加锁会影响程序
的性能,除非涉及到多线程数据安全才需要加锁,其他情况建议不要加锁。
加锁的代码要尽量的少。



以上是关于dll文件在同一个程序的多线程情况下,是共享的吗?的主要内容,如果未能解决你的问题,请参考以下文章

可能是东半球最好的多线程讲义!

总结下自己理解的多线程知识

总结下自己理解的多线程知识

我的 MFC C++ .dll 的多线程

Flask 中的全局变量是线程安全的吗?如何在请求之间共享数据?

线程--Java线程的互斥技术