The way, way, way simple response is hyperthreading is an emulation of dual-CPUs (or dual-core CPUs) done by a single-core processor. An Instruction Pointer is the register and pre-fetch logic that keeps track of where an application is in it's code. On single-core CPUs without HT, there is only one IP. If an application disables interrupts, then only the next bit of code that it's IP is pointing to can run. If an application in that state has a wait condition, or a loop, and never relinquishes the IP, then it hangs (temporarily or worse!) the system - you can see that quite a bit on a single CPU system.
HT tries to allievate that. It accomplishes this by having two Instruction Pointers (and some other bit obviously) that make it appear that it can handle two code threads instead of one. It actually DOESN'T have all the other core CPU bits, like a full extra set of registers, math units, etc. But it does try to overlap those two IP code streams by utilizing CPU sections that are not being used. Critically, if the code of one IP is looping or waiting, the OTHER IP still can utilize the system and execute...thus, systems with HT are less likely to enter wait or hung conditions, which usually amounts to a smoother user experience - and a little more efficient use of CPU resources in some applications or multiple applications
However, in today's world of cheap dual-core chips, HT has been eclipsed. Dual-core chips not only have two IPs - they have two whole processors. This means that the two streams of code no longer have to share registers, math units, etc. They are actually a dual-CPU system, but on one microprocessor. The user experience can be extremely smooth. and they can add even further performance to some applications, and especially multiple applications.
Hope that helps...
Future Shock